From 3182a1398a02a930396bd0192bda2a9ed3dacd6f Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Wed, 2 Aug 2023 21:42:08 +0000 Subject: [PATCH 01/50] target/cortex_m: Add Realtek Real-M200 and M300 These cores are advertised as M23 and M33 compatible, but are identified by the Realtek implementor id. These cores are found on the RTL872xD family, at least. Raw CPUIDs: Real-M200 (KM0): 721cd200 Real-M300 (KM4): 721fd220 Change-Id: I4106ccb7e8c562f98072a71e9e818f57999d664e Signed-off-by: Karl Palsson Reviewed-on: https://review.openocd.org/c/openocd/+/7846 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm.h | 1 + src/target/cortex_m.c | 11 +++++++++++ src/target/cortex_m.h | 2 ++ 3 files changed, 14 insertions(+) diff --git a/src/target/arm.h b/src/target/arm.h index f3abd6cbab..28e5330191 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -61,6 +61,7 @@ enum arm_arch { /** Known ARM implementor IDs */ enum arm_implementor { ARM_IMPLEMENTOR_ARM = 0x41, + ARM_IMPLEMENTOR_REALTEK = 0x72, }; /** diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 87a8845527..014ceaebaa 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -111,6 +111,17 @@ static const struct cortex_m_part_info cortex_m_parts[] = { .arch = ARM_ARCH_V8M, .flags = CORTEX_M_F_HAS_FPV5, }, + { + .impl_part = REALTEK_M200_PARTNO, + .name = "Real-M200 (KM0)", + .arch = ARM_ARCH_V8M, + }, + { + .impl_part = REALTEK_M300_PARTNO, + .name = "Real-M300 (KM4)", + .arch = ARM_ARCH_V8M, + .flags = CORTEX_M_F_HAS_FPV5, + }, }; /* forward declarations */ diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 806ff59106..b5d1da7f24 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -56,6 +56,8 @@ enum cortex_m_impl_part { CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21), CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31), CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22), + REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20), + REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22), }; /* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */ From c76e30c8bc2c1c14c06b18e66fd211c64835dbe4 Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Tue, 1 Aug 2023 00:02:36 +0000 Subject: [PATCH 02/50] tcl/target: add Realtek RTL872xD config Sufficient to probe both cores via multiple APs. No support listed for jtag in the datasheet or usermanual. Tested against a BW-16 board: https://www.amebaiot.com/en/amebad/#partner_bw16 Change-Id: Idf82085e7b7327fdf3d6d668e6fb59eff6e0431b Signed-off-by: Karl Palsson Reviewed-on: https://review.openocd.org/c/openocd/+/7847 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/rtl872xd.cfg | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 tcl/target/rtl872xd.cfg diff --git a/tcl/target/rtl872xd.cfg b/tcl/target/rtl872xd.cfg new file mode 100644 index 0000000000..65730e217f --- /dev/null +++ b/tcl/target/rtl872xd.cfg @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later OR MIT +# Realtek RTL872xD (ARM Cortex-M33 + M23, wifi+bt dualband soc) + +# HLA does not support AP other than 0 +if { [using_hla] } { + echo "ERROR: HLA transport cannot work with this target." + shutdown +} + +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME rtl872xd +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x6ba02477 +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME.km0 cortex_m -endian little -dap $_CHIPNAME.dap -ap-num 1 +target create $_TARGETNAME.km4 cortex_m -endian little -dap $_CHIPNAME.dap -ap-num 2 + +cortex_m reset_config sysresetreq + +adapter speed 1000 From c213ffe85fc6bfb5e199fa9ed994f8984c4cf0c9 Mon Sep 17 00:00:00 2001 From: Bruno Mendes Date: Tue, 8 Aug 2023 15:19:41 +0100 Subject: [PATCH 03/50] rtos/zephyr: arm: fetch arm exc return offset Since zephyrproject-rtos/zephyr@c3eeae8, Zephyr OS exposes offset of mode_exc_return in the arch struct for ARM. Accounting for this allows for consistency and enables logic with further offsets that may be added after this. Signed-off-by: Bruno Mendes Change-Id: Id53ebd80c5d98a7d94eb6b00ad638ce51e719822 Reviewed-on: https://review.openocd.org/c/openocd/+/7851 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/rtos/zephyr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rtos/zephyr.c b/src/rtos/zephyr.c index 934a8dd1cc..a4c60904b5 100644 --- a/src/rtos/zephyr.c +++ b/src/rtos/zephyr.c @@ -57,6 +57,7 @@ enum zephyr_offsets { OFFSET_T_ARCH, OFFSET_T_PREEMPT_FLOAT, OFFSET_T_COOP_FLOAT, + OFFSET_T_ARM_EXC_RETURN, OFFSET_MAX }; From 154d7f5e185d80a4e49920bed917551b76ace858 Mon Sep 17 00:00:00 2001 From: Jason Kacines Date: Wed, 9 Aug 2023 09:07:28 -0500 Subject: [PATCH 04/50] tcl/target/ti_k3: Add missing documentation for supported SoCs Add links for the SoCs are supported by the conf file for future reference. Change-Id: Ic5b7786ef3ac31414fe2ce56c1237a18ce99aaa1 Signed-off-by: Jason Kacines Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/7853 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- tcl/target/ti_k3.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index 2454357fc3..20b78ba895 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -8,8 +8,12 @@ # Has 2 ARMV8 Cores and 6 R5 Cores and an M3 # * J7200: https://www.ti.com/lit/pdf/spruiu1 # Has 2 ARMV8 Cores and 4 R5 Cores and an M3 +# * J721S2: https://www.ti.com/lit/pdf/spruj28 +# Has 2 ARMV8 Cores and 6 R5 Cores and an M4F # * AM642: https://www.ti.com/lit/pdf/spruim2 # Has 2 ARMV8 Cores and 4 R5 Cores, M4F and an M3 +# * AM625: https://www.ti.com/lit/pdf/spruiv7a +# Has 4 ARMV8 Cores and 1 R5 Core and an M4F # source [find target/swj-dp.tcl] From 627e949fc67eb7e77dd9fb3c51d3e0e8899e04ea Mon Sep 17 00:00:00 2001 From: Jason Kacines Date: Wed, 9 Aug 2023 09:10:13 -0500 Subject: [PATCH 05/50] tcl/target/ti_k3: Add AM62A7 SoC Add support for the TI K3 family AM62A7 SoC. For further details, see https://www.ti.com/lit/pdf/spruj16a Change-Id: Ie69bde4895f34b04f9967f63d1ca9c8149c50b8a Signed-off-by: Jason Kacines Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/7854 Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek Tested-by: jenkins --- tcl/target/ti_k3.cfg | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index 20b78ba895..99b5b51a30 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -14,6 +14,8 @@ # Has 2 ARMV8 Cores and 4 R5 Cores, M4F and an M3 # * AM625: https://www.ti.com/lit/pdf/spruiv7a # Has 4 ARMV8 Cores and 1 R5 Core and an M4F +# * AM62a7: https://www.ti.com/lit/pdf/spruj16a +# Has 4 ARMV8 Cores and 2 R5 Cores # source [find target/swj-dp.tcl] @@ -119,6 +121,27 @@ switch $_soc { set _gp_mcu_cores 1 set _gp_mcu_ap_unlock_offsets {0xf0 0x7c} } + am62a7 { + set _CHIPNAME am62a7 + set _K3_DAP_TAPID 0x0bb8d02f + + # AM62a7 has 1 clusters of 4 A53 cores. + set _armv8_cpu_name a53 + set _armv8_cores 4 + set ARMV8_DBGBASE {0x90010000 0x90110000 0x90210000 0x90310000} + set ARMV8_CTIBASE {0x90020000 0x90120000 0x90220000 0x90320000} + + # AM62a7 has 2 cluster of 1 R5s core. + set _r5_cores 2 + set R5_NAMES {main0_r5.0 mcu0_r5.0} + set R5_DBGBASE {0x9d410000 0x9d810000} + set R5_CTIBASE {0x9d418000 0x9d818000} + + # sysctrl CTI base + set CM3_CTIBASE {0x20001000} + # Sysctrl power-ap unlock offsets + set _sysctrl_ap_unlock_offsets {0xf0 0x78} + } j721e { set _CHIPNAME j721e set _K3_DAP_TAPID 0x0bb6402f From 02e4d7195ce9cdb3144fcc6d3a42134e2e8361b6 Mon Sep 17 00:00:00 2001 From: Jason Kacines Date: Tue, 8 Aug 2023 15:37:38 -0500 Subject: [PATCH 06/50] tcl/board: add TI am62a7evm config Add basic connection details with am625 SK/EVM For further details, see https://www.ti.com/tool/SK-AM62A-LP Change-Id: I0b6b4004f3a04be7a90207e44c588a4f68aff47a Signed-off-by: Jason Kacines Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/7855 Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek Tested-by: jenkins --- tcl/board/ti_am62a7evm.cfg | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tcl/board/ti_am62a7evm.cfg diff --git a/tcl/board/ti_am62a7evm.cfg b/tcl/board/ti_am62a7evm.cfg new file mode 100644 index 0000000000..e40790950b --- /dev/null +++ b/tcl/board/ti_am62a7evm.cfg @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments am62a7 EVM/SK +# Link: https://www.ti.com/tool/SK-AM62A-LP +# + +# AM62a7 EVM/SK has an xds110 onboard. +source [find interface/xds110.cfg] + +transport select jtag + +# default JTAG configuration has only SRST and no TRST +reset_config srst_only srst_push_pull + +# delay after SRST goes inactive +adapter srst delay 20 + +if { ![info exists SOC] } { + set SOC am62a7 +} + +source [find target/ti_k3.cfg] + +adapter speed 2500 From 29a57545f6be5ca3ba31f46447b5226b0f604ea0 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 14 Jul 2022 16:37:54 -0500 Subject: [PATCH 07/50] jtag/drivers: Add dmem driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Direct memory driver support for CoreSight Access Port(AP). Even though we emulate SWD (serial wire debug), we aren't actually using swd. Instead, we are using a direct memory access to get to the register set. This is similar in approach to other fast access native drivers such as am335xgpio drivers. Example operation on Texas Instrument's AM62x K3 SoC: +-----------+ | OpenOCD | SoC mem map | on |--------------+ | Cortex-A53| | +-----------+ | | +-----------+ +-----v-----+ |Cortex-M4F |<───────| | +-----------+ | | | DebugSS | +-----------+ | | |Cortex-M4F |<───────| | +-----------+ +-----------+ Signed-off-by: Nishanth Menon Signed-off-by: Jason Peck Change-Id: I8470cb15348863dd844b2c0e3f63a9063cb032c6 Reviewed-on: https://review.openocd.org/c/openocd/+/7088 Tested-by: jenkins Reviewed-by: Antonio Borneo --- configure.ac | 15 ++ doc/openocd.texi | 60 ++++++ src/jtag/drivers/Makefile.am | 3 + src/jtag/drivers/dmem.c | 342 +++++++++++++++++++++++++++++++++++ src/jtag/interface.h | 1 + src/jtag/interfaces.c | 3 + 6 files changed, 424 insertions(+) create mode 100644 src/jtag/drivers/dmem.c diff --git a/configure.ac b/configure.ac index ecf8384bf8..a2442d40b5 100644 --- a/configure.ac +++ b/configure.ac @@ -242,6 +242,10 @@ AC_ARG_ENABLE([rshim], AS_HELP_STRING([--enable-rshim], [Enable building the rshim driver]), [build_rshim=$enableval], [build_rshim=no]) +AC_ARG_ENABLE([dmem], + AS_HELP_STRING([--enable-dmem], [Enable building the dmem driver]), + [build_dmem=$enableval], [build_dmem=no]) + m4_define([AC_ARG_ADAPTERS], [ m4_foreach([adapter], [$1], [AC_ARG_ENABLE(ADAPTER_OPT([adapter]), @@ -358,6 +362,10 @@ AS_CASE([$host_os], AC_MSG_ERROR([build_rshim is only available on linux or freebsd]) ]) ]) + + AS_IF([test "x$build_dmem" = "xyes"], [ + AC_MSG_ERROR([dmem is only available on linux]) + ]) ]) AC_ARG_ENABLE([internal-jimtcl], @@ -478,6 +486,12 @@ AS_IF([test "x$build_rshim" = "xyes"], [ AC_DEFINE([BUILD_RSHIM], [0], [0 if you don't want to debug BlueField SoC via rshim.]) ]) +AS_IF([test "x$build_dmem" = "xyes"], [ + AC_DEFINE([BUILD_DMEM], [1], [1 if you want to debug via Direct Mem.]) +], [ + AC_DEFINE([BUILD_DMEM], [0], [0 if you don't want to debug via Direct Mem.]) +]) + AS_IF([test "x$build_dummy" = "xyes"], [ build_bitbang=yes AC_DEFINE([BUILD_DUMMY], [1], [1 if you want dummy driver.]) @@ -754,6 +768,7 @@ AM_CONDITIONAL([USE_LIBGPIOD], [test "x$use_libgpiod" = "xyes"]) AM_CONDITIONAL([USE_HIDAPI], [test "x$use_hidapi" = "xyes"]) AM_CONDITIONAL([USE_LIBJAYLINK], [test "x$use_libjaylink" = "xyes"]) AM_CONDITIONAL([RSHIM], [test "x$build_rshim" = "xyes"]) +AM_CONDITIONAL([DMEM], [test "x$build_dmem" = "xyes"]) AM_CONDITIONAL([HAVE_CAPSTONE], [test "x$enable_capstone" != "xno"]) AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"]) diff --git a/doc/openocd.texi b/doc/openocd.texi index 3348e472b0..6f16c9f709 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3568,6 +3568,66 @@ espusbjtag chip_id 1 @end deffn +@deffn {Interface Driver} {dmem} Direct Memory access debug interface + +The Texas Instruments K3 SoC family provides memory access to DAP +and coresight control registers. This allows control over the +microcontrollers directly from one of the processors on the SOC +itself. + +For maximum performance, the driver accesses the debug registers +directly over the SoC memory map. The memory mapping requires read +and write permission to kernel memory via "/dev/mem" and assumes that +the system firewall configurations permit direct access to the debug +memory space. + +@verbatim ++-----------+ +| OpenOCD | SoC mem map (/dev/mem) +| on +--------------+ +| Cortex-A53| | ++-----------+ | + | ++-----------+ +-----v-----+ +|Cortex-M4F <--------+ | ++-----------+ | | + | DebugSS | ++-----------+ | | +|Cortex-M4F <--------+ | ++-----------+ +-----------+ +@end verbatim + +NOTE: Firewalls are configurable in K3 SoC and depending on various types of +device configuration, this function may be blocked out. Typical behavior +observed in such cases is a firewall exception report on the security +controller and armv8 processor reporting a system error. + +See @file{tcl/interface/ti_k3_am625-swd-native.cfg} for a sample configuration +file. + +@deffn {Command} {dmem info} +Print the DAPBUS dmem configuration. +@end deffn + +@deffn {Config Command} {dmem device} device_path +Set the DAPBUS memory access device (default: /dev/mem). +@end deffn + +@deffn {Config Command} {dmem base_address} base_address +Set the DAPBUS base address which is used to access CoreSight +compliant Access Ports (APs) directly. +@end deffn + +@deffn {Config Command} {dmem ap_address_offset} offset_address +Set the address offset between Access Ports (APs). +@end deffn + +@deffn {Config Command} {dmem max_aps} n +Set the maximum number of valid access ports on the SoC. +@end deffn + +@end deffn + @section Transport Configuration @cindex Transport As noted earlier, depending on the version of OpenOCD you use, diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 4b2dbc44db..e404afe9f0 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -161,6 +161,9 @@ endif if RSHIM DRIVERFILES += %D%/rshim.c endif +if DMEM +DRIVERFILES += %D%/dmem.c +endif if OSBDM DRIVERFILES += %D%/osbdm.c endif diff --git a/src/jtag/drivers/dmem.c b/src/jtag/drivers/dmem.c new file mode 100644 index 0000000000..8d603ad633 --- /dev/null +++ b/src/jtag/drivers/dmem.c @@ -0,0 +1,342 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ */ + +/** + * @file + * This file implements support for the Direct memory access to CoreSight + * Access Ports (APs) or emulate the same to access CoreSight debug registers + * directly. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +static void *dmem_map_base, *dmem_virt_base_addr; +static size_t dmem_mapped_size; + +/* Default dmem device. */ +#define DMEM_DEV_PATH_DEFAULT "/dev/mem" +static char *dmem_dev_path; +static uint64_t dmem_dap_base_address; +static unsigned int dmem_dap_max_aps = 1; +static uint32_t dmem_dap_ap_offset = 0x100; + +/* AP MODE */ +static uint32_t dmem_get_ap_reg_offset(struct adiv5_ap *ap, unsigned int reg) +{ + return (dmem_dap_ap_offset * ap->ap_num) + reg; +} + +static void dmem_set_ap_reg(struct adiv5_ap *ap, unsigned int reg, uint32_t val) +{ + *(volatile uint32_t *)((uintptr_t)dmem_virt_base_addr + + dmem_get_ap_reg_offset(ap, reg)) = val; +} + +static uint32_t dmem_get_ap_reg(struct adiv5_ap *ap, unsigned int reg) +{ + return *(volatile uint32_t *)((uintptr_t)dmem_virt_base_addr + + dmem_get_ap_reg_offset(ap, reg)); +} + +static int dmem_dp_q_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data) +{ + if (!data) + return ERROR_OK; + + switch (reg) { + case DP_CTRL_STAT: + *data = CDBGPWRUPACK | CSYSPWRUPACK; + break; + + default: + *data = 0; + break; + } + + return ERROR_OK; +} + +static int dmem_dp_q_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data) +{ + return ERROR_OK; +} + +static int dmem_ap_q_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) +{ + if (is_adiv6(ap->dap)) { + static bool error_flagged; + + if (!error_flagged) + LOG_ERROR("ADIv6 dap not supported by dmem dap-direct mode"); + + error_flagged = true; + + return ERROR_FAIL; + } + + *data = dmem_get_ap_reg(ap, reg); + + return ERROR_OK; +} + +static int dmem_ap_q_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) +{ + if (is_adiv6(ap->dap)) { + static bool error_flagged; + + if (!error_flagged) + LOG_ERROR("ADIv6 dap not supported by dmem dap-direct mode"); + + error_flagged = true; + + return ERROR_FAIL; + } + + dmem_set_ap_reg(ap, reg, data); + + return ERROR_OK; +} + +static int dmem_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack) +{ + return ERROR_OK; +} + +static int dmem_dp_run(struct adiv5_dap *dap) +{ + return ERROR_OK; +} + +static int dmem_connect(struct adiv5_dap *dap) +{ + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_dap_device_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + free(dmem_dev_path); + dmem_dev_path = strdup(CMD_ARGV[0]); + + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_dap_base_address_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], dmem_dap_base_address); + + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_dap_max_aps_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], dmem_dap_max_aps); + + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_dap_ap_offset_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], dmem_dap_ap_offset); + + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_dap_config_info_command) +{ + if (CMD_ARGC != 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + command_print(CMD, "dmem (Direct Memory) AP Adapter Configuration:"); + command_print(CMD, " Device : %s", + dmem_dev_path ? dmem_dev_path : DMEM_DEV_PATH_DEFAULT); + command_print(CMD, " Base Address : 0x%" PRIx64, dmem_dap_base_address); + command_print(CMD, " Max APs : %u", dmem_dap_max_aps); + command_print(CMD, " AP offset : 0x%08" PRIx32, dmem_dap_ap_offset); + + return ERROR_OK; +} + +static const struct command_registration dmem_dap_subcommand_handlers[] = { + { + .name = "info", + .handler = dmem_dap_config_info_command, + .mode = COMMAND_ANY, + .help = "print the config info", + .usage = "", + }, + { + .name = "device", + .handler = dmem_dap_device_command, + .mode = COMMAND_CONFIG, + .help = "set the dmem memory access device (default: /dev/mem)", + .usage = "device_path", + }, + { + .name = "base_address", + .handler = dmem_dap_base_address_command, + .mode = COMMAND_CONFIG, + .help = "set the dmem dap AP memory map base address", + .usage = "base_address", + }, + { + .name = "ap_address_offset", + .handler = dmem_dap_ap_offset_command, + .mode = COMMAND_CONFIG, + .help = "set the offsets of each ap index", + .usage = "offset_address", + }, + { + .name = "max_aps", + .handler = dmem_dap_max_aps_command, + .mode = COMMAND_CONFIG, + .help = "set the maximum number of APs this will support", + .usage = "n", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration dmem_dap_command_handlers[] = { + { + .name = "dmem", + .mode = COMMAND_ANY, + .help = "Perform dmem (Direct Memory) DAP management and configuration", + .chain = dmem_dap_subcommand_handlers, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +static int dmem_dap_init(void) +{ + char *path = dmem_dev_path ? dmem_dev_path : DMEM_DEV_PATH_DEFAULT; + uint32_t dmem_total_memory_window_size; + long page_size = sysconf(_SC_PAGESIZE); + size_t dmem_mapped_start, dmem_mapped_end; + long start_delta; + int dmem_fd; + + if (!dmem_dap_base_address) { + LOG_ERROR("dmem DAP Base address NOT set? value is 0"); + return ERROR_FAIL; + } + + dmem_fd = open(path, O_RDWR | O_SYNC); + if (dmem_fd == -1) { + LOG_ERROR("Unable to open %s", path); + return ERROR_FAIL; + } + + dmem_total_memory_window_size = (dmem_dap_max_aps + 1) * dmem_dap_ap_offset; + + dmem_mapped_start = dmem_dap_base_address; + dmem_mapped_end = dmem_dap_base_address + dmem_total_memory_window_size; + /* mmap() requires page aligned offsets */ + dmem_mapped_start = ALIGN_DOWN(dmem_mapped_start, page_size); + dmem_mapped_end = ALIGN_UP(dmem_mapped_end, page_size); + + dmem_mapped_size = dmem_mapped_end - dmem_mapped_start; + start_delta = dmem_mapped_start - dmem_dap_base_address; + + dmem_map_base = mmap(NULL, + dmem_mapped_size, + (PROT_READ | PROT_WRITE), + MAP_SHARED, dmem_fd, + dmem_mapped_start); + + close(dmem_fd); + + if (dmem_map_base == MAP_FAILED) { + LOG_ERROR("Mapping address 0x%lx for 0x%lx bytes failed!", + dmem_mapped_start, dmem_mapped_size); + return ERROR_FAIL; + } + + dmem_virt_base_addr = (void *)((uintptr_t)dmem_map_base + start_delta); + + return ERROR_OK; +} + +static int dmem_dap_quit(void) +{ + if (munmap(dmem_map_base, dmem_mapped_size) == -1) + LOG_ERROR("%s: Failed to unmap mapped memory!", __func__); + + return ERROR_OK; +} + +static int dmem_dap_reset(int req_trst, int req_srst) +{ + return ERROR_OK; +} + +static int dmem_dap_speed(int speed) +{ + return ERROR_OK; +} + +static int dmem_dap_khz(int khz, int *jtag_speed) +{ + *jtag_speed = khz; + return ERROR_OK; +} + +static int dmem_dap_speed_div(int speed, int *khz) +{ + *khz = speed; + return ERROR_OK; +} + +/* DAP operations. */ +static const struct dap_ops dmem_dap_ops = { + .connect = dmem_connect, + .queue_dp_read = dmem_dp_q_read, + .queue_dp_write = dmem_dp_q_write, + .queue_ap_read = dmem_ap_q_read, + .queue_ap_write = dmem_ap_q_write, + .queue_ap_abort = dmem_ap_q_abort, + .run = dmem_dp_run, +}; + +static const char *const dmem_dap_transport[] = { "dapdirect_swd", NULL }; + +struct adapter_driver dmem_dap_adapter_driver = { + .name = "dmem", + .transports = dmem_dap_transport, + .commands = dmem_dap_command_handlers, + + .init = dmem_dap_init, + .quit = dmem_dap_quit, + .reset = dmem_dap_reset, + .speed = dmem_dap_speed, + .khz = dmem_dap_khz, + .speed_div = dmem_dap_speed_div, + + .dap_swd_ops = &dmem_dap_ops, +}; diff --git a/src/jtag/interface.h b/src/jtag/interface.h index 25ae7e8a16..3df424086d 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -370,6 +370,7 @@ extern struct adapter_driver at91rm9200_adapter_driver; extern struct adapter_driver bcm2835gpio_adapter_driver; extern struct adapter_driver buspirate_adapter_driver; extern struct adapter_driver cmsis_dap_adapter_driver; +extern struct adapter_driver dmem_dap_adapter_driver; extern struct adapter_driver dummy_adapter_driver; extern struct adapter_driver ep93xx_adapter_driver; extern struct adapter_driver esp_usb_adapter_driver; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index aa0ad3ade1..c24ead8cd9 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -147,6 +147,9 @@ struct adapter_driver *adapter_drivers[] = { #if BUILD_RSHIM == 1 &rshim_dap_adapter_driver, #endif +#if BUILD_DMEM == 1 + &dmem_dap_adapter_driver, +#endif #if BUILD_AM335XGPIO == 1 &am335xgpio_adapter_driver, #endif From 42872d18bf1326294521096b73314e54a31b0b60 Mon Sep 17 00:00:00 2001 From: Jason Peck Date: Mon, 18 Jul 2022 13:45:05 -0500 Subject: [PATCH 08/50] jtag/drivers: dmem: Add Emulated AP mode This emulation mode supports software translation of an AP request into an address mapped transaction that does not rely on physical AP hardware. This is necessary in some hardware such as K3 SoCs since the hardware architecture anticipates a potential race condition between AP doing direct memory access generating transactions back to system bus and firewalls that data path out. This emulation mode allows direct memory driver to emulate CoreSight Access Port (AP) and reuse the SoC configuration meant for JTAG debuggers. Since the address ranges are flat in nature, the requisite memory base and size will need to be provided a-priori to the driver for mapping. The other design alternative would be to map requested memory map for every register operation, but, that would defeat our intent of getting max debug performance. Signed-off-by: Nishanth Menon Signed-off-by: Jason Peck Change-Id: I2d3c5f7833f1973e90b4f6b247827f62fc2905d0 Reviewed-on: https://review.openocd.org/c/openocd/+/7089 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 13 ++ src/jtag/drivers/dmem.c | 292 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 299 insertions(+), 6 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 6f16c9f709..d07188c4bc 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3626,6 +3626,19 @@ Set the address offset between Access Ports (APs). Set the maximum number of valid access ports on the SoC. @end deffn +@deffn {Config Command} {dmem emu_ap_list} n +Set the list of Access Ports (APs) that need to be emulated. This +emulation mode supports software translation of an AP request into an +address mapped transaction that does not rely on physical AP hardware. +This maybe needed if the AP is either denied access via memory map or +protected using other SoC mechanisms. +@end deffn + +@deffn {Config Command} {dmem emu_base_address_range} base_address address_window_size +Set the emulated address and address window size. Both of these +parameters must be aligned to page size. +@end deffn + @end deffn @section Transport Configuration diff --git a/src/jtag/drivers/dmem.c b/src/jtag/drivers/dmem.c index 8d603ad633..4dc582115c 100644 --- a/src/jtag/drivers/dmem.c +++ b/src/jtag/drivers/dmem.c @@ -25,6 +25,19 @@ #include #include +struct dmem_emu_ap_info { + uint64_t ap_num; + /* Emulation mode AP state variables */ + uint32_t apbap_tar; + uint32_t apbap_csw; +}; + +/* + * This bit tells if the transaction is coming in from jtag or not + * we just mask this out to emulate direct address access + */ +#define ARM_APB_PADDR31 BIT(31) + static void *dmem_map_base, *dmem_virt_base_addr; static size_t dmem_mapped_size; @@ -35,6 +48,176 @@ static uint64_t dmem_dap_base_address; static unsigned int dmem_dap_max_aps = 1; static uint32_t dmem_dap_ap_offset = 0x100; +/* DAP error code. */ +static int dmem_dap_retval = ERROR_OK; + +/* AP Emulation Mode */ +static uint64_t dmem_emu_base_address; +static uint64_t dmem_emu_size; +static void *dmem_emu_map_base, *dmem_emu_virt_base_addr; +static size_t dmem_emu_mapped_size; +#define DMEM_MAX_EMULATE_APS 5 +static unsigned int dmem_emu_ap_count; +static struct dmem_emu_ap_info dmem_emu_ap_list[DMEM_MAX_EMULATE_APS]; + +/* + * This helper is used to determine the TAR increment size in bytes. The AP's + * CSW encoding for SIZE supports byte count decode using "1 << SIZE". + */ +static uint32_t dmem_memap_tar_inc(uint32_t csw) +{ + if ((csw & CSW_ADDRINC_MASK) != 0) + return 1 << (csw & CSW_SIZE_MASK); + return 0; +} + +/* + * EMULATION MODE: In Emulation MODE, we assume the following: + * TCL still describes as system is operational from the view of AP (ex. jtag) + * However, the hardware doesn't permit direct memory access to these APs + * (only permitted via JTAG). + * + * So, the access to these APs have to be decoded to a memory map + * access which we can directly access. + * + * A few TI processors have this issue. + */ +static bool dmem_is_emulated_ap(struct adiv5_ap *ap, unsigned int *idx) +{ + for (unsigned int i = 0; i < dmem_emu_ap_count; i++) { + if (ap->ap_num == dmem_emu_ap_list[i].ap_num) { + *idx = i; + return true; + } + } + return false; +} + +static void dmem_emu_set_ap_reg(uint64_t addr, uint32_t val) +{ + addr &= ~ARM_APB_PADDR31; + + *(volatile uint32_t *)((uintptr_t)dmem_emu_virt_base_addr + addr) = val; +} + +static uint32_t dmem_emu_get_ap_reg(uint64_t addr) +{ + uint32_t val; + + addr &= ~ARM_APB_PADDR31; + + val = *(volatile uint32_t *)((uintptr_t)dmem_emu_virt_base_addr + addr); + + return val; +} + +static int dmem_emu_ap_q_read(unsigned int ap_idx, unsigned int reg, uint32_t *data) +{ + uint64_t addr; + int ret = ERROR_OK; + struct dmem_emu_ap_info *ap_info = &dmem_emu_ap_list[ap_idx]; + + switch (reg) { + case ADIV5_MEM_AP_REG_CSW: + *data = ap_info->apbap_csw; + break; + case ADIV5_MEM_AP_REG_TAR: + *data = ap_info->apbap_tar; + break; + case ADIV5_MEM_AP_REG_CFG: + *data = 0; + break; + case ADIV5_MEM_AP_REG_BASE: + *data = 0; + break; + case ADIV5_AP_REG_IDR: + *data = 0; + break; + case ADIV5_MEM_AP_REG_BD0: + case ADIV5_MEM_AP_REG_BD1: + case ADIV5_MEM_AP_REG_BD2: + case ADIV5_MEM_AP_REG_BD3: + addr = (ap_info->apbap_tar & ~0xf) + (reg & 0x0C); + + *data = dmem_emu_get_ap_reg(addr); + + break; + case ADIV5_MEM_AP_REG_DRW: + addr = ap_info->apbap_tar; + + *data = dmem_emu_get_ap_reg(addr); + + ap_info->apbap_tar += dmem_memap_tar_inc(ap_info->apbap_csw); + break; + default: + LOG_INFO("%s: Unknown reg: 0x%02x", __func__, reg); + ret = ERROR_FAIL; + break; + } + + /* Track the last error code. */ + if (ret != ERROR_OK) + dmem_dap_retval = ret; + + return ret; +} + +static int dmem_emu_ap_q_write(unsigned int ap_idx, unsigned int reg, uint32_t data) +{ + uint64_t addr; + int ret = ERROR_OK; + struct dmem_emu_ap_info *ap_info = &dmem_emu_ap_list[ap_idx]; + + switch (reg) { + case ADIV5_MEM_AP_REG_CSW: + /* + * This implementation only supports 32-bit accesses. + * Force this by ensuring CSW_SIZE field indicates 32-BIT. + */ + ap_info->apbap_csw = ((data & ~CSW_SIZE_MASK) | CSW_32BIT); + break; + case ADIV5_MEM_AP_REG_TAR: + /* + * This implementation only supports 32-bit accesses. + * Force LS 2-bits of TAR to 00b + */ + ap_info->apbap_tar = (data & ~0x3); + break; + + case ADIV5_MEM_AP_REG_CFG: + case ADIV5_MEM_AP_REG_BASE: + case ADIV5_AP_REG_IDR: + /* We don't use this, so we don't need to store */ + break; + + case ADIV5_MEM_AP_REG_BD0: + case ADIV5_MEM_AP_REG_BD1: + case ADIV5_MEM_AP_REG_BD2: + case ADIV5_MEM_AP_REG_BD3: + addr = (ap_info->apbap_tar & ~0xf) + (reg & 0x0C); + + dmem_emu_set_ap_reg(addr, data); + + break; + case ADIV5_MEM_AP_REG_DRW: + addr = ap_info->apbap_tar; + dmem_emu_set_ap_reg(addr, data); + + ap_info->apbap_tar += dmem_memap_tar_inc(ap_info->apbap_csw); + break; + default: + LOG_INFO("%s: Unknown reg: 0x%02x", __func__, reg); + ret = EINVAL; + break; + } + + /* Track the last error code. */ + if (ret != ERROR_OK) + dmem_dap_retval = ret; + + return ret; +} + /* AP MODE */ static uint32_t dmem_get_ap_reg_offset(struct adiv5_ap *ap, unsigned int reg) { @@ -78,6 +261,8 @@ static int dmem_dp_q_write(struct adiv5_dap *dap, unsigned int reg, uint32_t dat static int dmem_ap_q_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) { + unsigned int idx; + if (is_adiv6(ap->dap)) { static bool error_flagged; @@ -89,6 +274,9 @@ static int dmem_ap_q_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) return ERROR_FAIL; } + if (dmem_is_emulated_ap(ap, &idx)) + return dmem_emu_ap_q_read(idx, reg, data); + *data = dmem_get_ap_reg(ap, reg); return ERROR_OK; @@ -96,6 +284,8 @@ static int dmem_ap_q_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) static int dmem_ap_q_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) { + unsigned int idx; + if (is_adiv6(ap->dap)) { static bool error_flagged; @@ -107,6 +297,9 @@ static int dmem_ap_q_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) return ERROR_FAIL; } + if (dmem_is_emulated_ap(ap, &idx)) + return dmem_emu_ap_q_write(idx, reg, data); + dmem_set_ap_reg(ap, reg, data); return ERROR_OK; @@ -119,7 +312,12 @@ static int dmem_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack) static int dmem_dp_run(struct adiv5_dap *dap) { - return ERROR_OK; + int retval = dmem_dap_retval; + + /* Clear the error code. */ + dmem_dap_retval = ERROR_OK; + + return retval; } static int dmem_connect(struct adiv5_dap *dap) @@ -168,6 +366,34 @@ COMMAND_HANDLER(dmem_dap_ap_offset_command) return ERROR_OK; } +COMMAND_HANDLER(dmem_emu_base_address_command) +{ + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], dmem_emu_base_address); + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], dmem_emu_size); + + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_emu_ap_list_command) +{ + uint64_t em_ap; + + if (CMD_ARGC < 1 || CMD_ARGC > DMEM_MAX_EMULATE_APS) + return ERROR_COMMAND_SYNTAX_ERROR; + + for (unsigned int i = 0; i < CMD_ARGC; i++) { + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[i], em_ap); + dmem_emu_ap_list[i].ap_num = em_ap; + } + + dmem_emu_ap_count = CMD_ARGC; + + return ERROR_OK; +} + COMMAND_HANDLER(dmem_dap_config_info_command) { if (CMD_ARGC != 0) @@ -179,7 +405,16 @@ COMMAND_HANDLER(dmem_dap_config_info_command) command_print(CMD, " Base Address : 0x%" PRIx64, dmem_dap_base_address); command_print(CMD, " Max APs : %u", dmem_dap_max_aps); command_print(CMD, " AP offset : 0x%08" PRIx32, dmem_dap_ap_offset); - + command_print(CMD, " Emulated AP Count : %u", dmem_emu_ap_count); + + if (dmem_emu_ap_count) { + command_print(CMD, " Emulated AP details:"); + command_print(CMD, " Emulated address : 0x%" PRIx64, dmem_emu_base_address); + command_print(CMD, " Emulated size : 0x%" PRIx64, dmem_emu_size); + for (unsigned int i = 0; i < dmem_emu_ap_count; i++) + command_print(CMD, " Emulated AP [%u] : %" PRIx64, i, + dmem_emu_ap_list[i].ap_num); + } return ERROR_OK; } @@ -219,6 +454,20 @@ static const struct command_registration dmem_dap_subcommand_handlers[] = { .help = "set the maximum number of APs this will support", .usage = "n", }, + { + .name = "emu_ap_list", + .handler = dmem_emu_ap_list_command, + .mode = COMMAND_CONFIG, + .help = "set the list of AP indices to be emulated (upto max)", + .usage = "n", + }, + { + .name = "emu_base_address_range", + .handler = dmem_emu_base_address_command, + .mode = COMMAND_CONFIG, + .help = "set the base address and size of emulated AP range (all emulated APs access this range)", + .usage = "base_address address_window_size", + }, COMMAND_REGISTRATION_DONE }; @@ -269,18 +518,45 @@ static int dmem_dap_init(void) (PROT_READ | PROT_WRITE), MAP_SHARED, dmem_fd, dmem_mapped_start); - - close(dmem_fd); - if (dmem_map_base == MAP_FAILED) { LOG_ERROR("Mapping address 0x%lx for 0x%lx bytes failed!", dmem_mapped_start, dmem_mapped_size); - return ERROR_FAIL; + goto error_fail; } dmem_virt_base_addr = (void *)((uintptr_t)dmem_map_base + start_delta); + /* Lets Map the emulated address if necessary */ + if (dmem_emu_ap_count) { + dmem_mapped_start = dmem_emu_base_address; + dmem_mapped_end = dmem_emu_base_address + dmem_emu_size; + /* mmap() requires page aligned offsets */ + dmem_mapped_start = ALIGN_DOWN(dmem_mapped_start, page_size); + dmem_mapped_end = ALIGN_UP(dmem_mapped_end, page_size); + + dmem_emu_mapped_size = dmem_mapped_end - dmem_mapped_start; + start_delta = dmem_mapped_start - dmem_emu_base_address; + + dmem_emu_map_base = mmap(NULL, + dmem_emu_mapped_size, + (PROT_READ | PROT_WRITE), + MAP_SHARED, dmem_fd, + dmem_mapped_start); + if (dmem_emu_map_base == MAP_FAILED) { + LOG_ERROR("Mapping EMU address 0x%lx for 0x%lx bytes failed!", + dmem_emu_base_address, dmem_emu_size); + goto error_fail; + } + dmem_emu_virt_base_addr = (void *)((uintptr_t)dmem_emu_map_base + + start_delta); + } + + close(dmem_fd); return ERROR_OK; + +error_fail: + close(dmem_fd); + return ERROR_FAIL; } static int dmem_dap_quit(void) @@ -288,6 +564,10 @@ static int dmem_dap_quit(void) if (munmap(dmem_map_base, dmem_mapped_size) == -1) LOG_ERROR("%s: Failed to unmap mapped memory!", __func__); + if (dmem_emu_ap_count + && munmap(dmem_emu_map_base, dmem_emu_mapped_size) == -1) + LOG_ERROR("%s: Failed to unmap emu mapped memory!", __func__); + return ERROR_OK; } From 3223b49c401a07b0b59d2e5ac80a1e9ec999e98b Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 14 Jul 2022 16:37:54 -0500 Subject: [PATCH 09/50] tcl/board: Add am625 native swd configuration Direct memory driver swd native configuration for am625. Signed-off-by: Nishanth Menon Signed-off-by: Jason Peck Change-Id: I6cf521fe9af0a4b8f8ab4853bc25722368b713e6 Reviewed-on: https://review.openocd.org/c/openocd/+/7091 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/board/ti_am625_swd_native.cfg | 22 ++++++++++++++++++++++ tcl/target/ti_k3.cfg | 29 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 tcl/board/ti_am625_swd_native.cfg diff --git a/tcl/board/ti_am625_swd_native.cfg b/tcl/board/ti_am625_swd_native.cfg new file mode 100644 index 0000000000..dc4b20579d --- /dev/null +++ b/tcl/board/ti_am625_swd_native.cfg @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-2023 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments am625 +# Link: https://www.ti.com/product/AM625 +# +# This configuration file is used as a self hosted debug configuration that +# works on every AM625 platform based on firewall configuration permitted +# in the system. +# +# In this system openOCD runs on one of the CPUs inside AM625 and provides +# network ports that can then be used to debug the microcontrollers on the +# SoC - either self hosted IDE OR remotely. + +# We are using dmem, which uses dapdirect_swd transport +adapter driver dmem + +if { ![info exists SOC] } { + set SOC am625 +} + +source [find target/ti_k3.cfg] diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index 99b5b51a30..ef1f1569a1 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -120,6 +120,16 @@ switch $_soc { # M4 processor set _gp_mcu_cores 1 set _gp_mcu_ap_unlock_offsets {0xf0 0x7c} + + # Setup DMEM access descriptions + # DAPBUS (Debugger) description + set _dmem_base_address 0x740002000 + set _dmem_ap_address_offset 0x100 + set _dmem_max_aps 10 + # Emulated AP description + set _dmem_emu_base_address 0x760000000 + set _dmem_emu_base_address_map_to 0x1d500000 + set _dmem_emu_ap_list 1 } am62a7 { set _CHIPNAME am62a7 @@ -329,3 +339,22 @@ if { $_gp_mcu_cores != 0 } { halt 1000 } } + +# In case of DMEM access, configure the dmem adapter with offsets from above. +if { 0 == [string compare [adapter name] dmem ] } { + if { [info exists _dmem_base_address] } { + # DAPBUS (Debugger) description + dmem base_address $_dmem_base_address + dmem ap_address_offset $_dmem_ap_address_offset + dmem max_aps $_dmem_max_aps + + # The following are the details of APs to be emulated for direct address access. + # Debug Config (Debugger) description + dmem emu_base_address_range $_dmem_emu_base_address $_dmem_emu_base_address_map_to + dmem emu_ap_list $_dmem_emu_ap_list + # We are going local bus, so speed is really dummy here. + adapter speed 2500 + } else { + puts "ERROR: ${SOC} data is missing to support dmem access!" + } +} From 76f3351f4a0a3c315bd257a18bc1e2c158d397bb Mon Sep 17 00:00:00 2001 From: Kaelin Laundry Date: Tue, 4 Oct 2022 13:11:02 -0500 Subject: [PATCH 10/50] tcl/board: Add j721e native swd configuration Direct memory driver swd native configuration for j721E Signed-off-by: Kaelin Laundry Signed-off-by: Nishanth Menon Change-Id: I27455040f48c47271ae110afd114fce005824969 Reviewed-on: https://review.openocd.org/c/openocd/+/7259 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/ti_j721e_swd_native.cfg | 21 +++++++++++++++++++++ tcl/target/ti_k3.cfg | 10 ++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tcl/board/ti_j721e_swd_native.cfg diff --git a/tcl/board/ti_j721e_swd_native.cfg b/tcl/board/ti_j721e_swd_native.cfg new file mode 100644 index 0000000000..3041c3c345 --- /dev/null +++ b/tcl/board/ti_j721e_swd_native.cfg @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-2023 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments TDA4VM/J721E +# Link: https://www.ti.com/product/TDA4VM +# +# This configuration file is used as a self hosted debug configuration that +# works on every TDA4VM platform based on firewall configuration permitted +# in the system. +# +# In this system openOCD runs on one of the CPUs inside TDA4VM and provides +# network ports that can then be used to debug the microcontrollers on the +# SoC - either self hosted IDE OR remotely. + +# We are using dmem, which uses dapdirect_swd transport +adapter driver dmem + +if { ![info exists SOC] } { + set SOC j721e +} +source [find target/ti_k3.cfg] diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index ef1f1569a1..f0881cdff7 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -161,6 +161,16 @@ switch $_soc { # J721E has 3 clusters of 2 R5 cores each. set _r5_cores 6 + + # Setup DMEM access descriptions + # DAPBUS (Debugger) description + set _dmem_base_address 0x4c40002000 + set _dmem_ap_address_offset 0x100 + set _dmem_max_aps 8 + # Emulated AP description + set _dmem_emu_base_address 0x4c60000000 + set _dmem_emu_base_address_map_to 0x1d600000 + set _dmem_emu_ap_list 1 } j7200 { set _CHIPNAME j7200 From 74325dc73d48eb9371fa9ba8d190c46d70abbce3 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Thu, 3 Aug 2023 17:43:39 +0200 Subject: [PATCH 11/50] stlink: increase stlink v2 max speed to 2.25 Mbps stlink v2 on Nucleo-64 board (e.g. NUCLEO-L476RG) has target SWO signal connected to STM32F103CB'S PA10, which is UART1_RX. UART1 within this MCU in theory can be configured to 4.5 Mbps baudrate, which means this is the upper limit supported by HW. As a confirmation BMP (Black Magic Probe) project also states in documentation that UART1 can be used with up to 4.5 Mbps baudrate. Tests have shown that configuring 4.5 Mbps baudrate on stlink v2 available on NUCLEO-L476RG board results in receiving corrupted data. Using 2.25 Mbps however allows to successfully receive all data from SWO. This makes sense in terms of STM32F103CB capabilities, since 2.25 Mbps is the next supported baudrate due to division by 2. Increase supported stlink v2 SWO speed from 2 to 2.25 Mbps. Tested with NUCLEO-L476RG: $ stm32l4x.tpiu configure -protocol uart \ -traceclk 80000000 -pin-freq 2250000 \ -output /dev/stdout $ stm32l4x.tpiu enable 2.25 Mbps speed confirmed with logic analyzer. Signed-off-by: Marcin Niestroj Change-Id: Icbec04585664aba8b217e8f9a75458e577f7617f Reviewed-on: https://review.openocd.org/c/openocd/+/7848 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/stlink_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 2c5b63dd6e..c5326a206a 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -456,7 +456,7 @@ static inline int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, i #define STLINK_DEBUG_PORT_ACCESS 0xffff #define STLINK_TRACE_SIZE 4096 -#define STLINK_TRACE_MAX_HZ 2000000 +#define STLINK_TRACE_MAX_HZ 2250000 #define STLINK_V3_TRACE_MAX_HZ 24000000 #define STLINK_V3_MAX_FREQ_NB 10 From 3b38226370b21ef1d644cbe303a85c36a58ef365 Mon Sep 17 00:00:00 2001 From: Artur Rojek Date: Sun, 13 Aug 2023 16:47:28 +0200 Subject: [PATCH 12/50] mips32: add per-cpu quirks feature Introduce the ability to detect CPUs based on CP0 PRId register and apply cpu specific quirks, which alter the default ejtag behavior. First of those is EJTAG_QUIRK_PAD_DRET, which makes sure extra NOPs are placed after the DRET instruction on exit from debug mode. This fixes resume behavior on Ingenic JZ4780 SoC. The proper detection of some (currently unsupported) CPUs becomes quite complicated, so please consult the following Linux kernel code when adding new CPUs: * arch/mips/include/asm/cpu.h * arch/mips/kernel/cpu-probe.c Change-Id: I0f413d5096cd43ef346b02cea85024985b7face6 Signed-off-by: Artur Rojek Signed-off-by: Paul Fertser Signed-off-by: Oleksij Rempel Reviewed-on: https://review.openocd.org/c/openocd/+/7859 Tested-by: jenkins --- src/target/Makefile.am | 1 + src/target/mips32.c | 58 +++++++++++++++++++++++++++++++++++++++++ src/target/mips32.h | 12 +++++++++ src/target/mips_cpu.h | 27 +++++++++++++++++++ src/target/mips_ejtag.c | 5 +++- src/target/mips_m4k.c | 2 ++ 6 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/target/mips_cpu.h diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 2084de65e6..1fc7d2afa6 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -204,6 +204,7 @@ ARC_SRC = \ %D%/image.h \ %D%/mips32.h \ %D%/mips64.h \ + %D%/mips_cpu.h \ %D%/mips_m4k.h \ %D%/mips_mips64.h \ %D%/mips_ejtag.h \ diff --git a/src/target/mips32.c b/src/target/mips32.c index ce16a7b5d6..4e6d25118e 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -18,6 +18,7 @@ #endif #include "mips32.h" +#include "mips_cpu.h" #include "breakpoints.h" #include "algorithm.h" #include "register.h" @@ -693,6 +694,63 @@ int mips32_enable_interrupts(struct target *target, int enable) return ERROR_OK; } +/* read processor identification cp0 register */ +static int mips32_read_c0_prid(struct target *target) +{ + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + int retval; + + retval = mips32_cp0_read(ejtag_info, &mips32->prid, 15, 0); + if (retval != ERROR_OK) { + LOG_ERROR("processor id not available, failed to read cp0 PRId register"); + mips32->prid = 0; + } + + return retval; +} + +/* + * Detect processor type and apply required quirks. + * + * NOTE: The proper detection of certain CPUs can become quite complicated. + * Please consult the following Linux kernel code when adding new CPUs: + * arch/mips/include/asm/cpu.h + * arch/mips/kernel/cpu-probe.c + */ +int mips32_cpu_probe(struct target *target) +{ + struct mips32_common *mips32 = target_to_mips32(target); + const char *cpu_name = "unknown"; + int retval; + + if (mips32->prid) + return ERROR_OK; /* Already probed once, return early. */ + + retval = mips32_read_c0_prid(target); + if (retval != ERROR_OK) + return retval; + + switch (mips32->prid & PRID_COMP_MASK) { + case PRID_COMP_INGENIC_E1: + switch (mips32->prid & PRID_IMP_MASK) { + case PRID_IMP_XBURST_REV1: + cpu_name = "Ingenic XBurst rev1"; + mips32->cpu_quirks |= EJTAG_QUIRK_PAD_DRET; + break; + default: + break; + } + break; + default: + break; + } + + LOG_DEBUG("CPU: %s (PRId %08x)", cpu_name, mips32->prid); + + return ERROR_OK; +} + /* read config to config3 cp0 registers and log isa implementation */ int mips32_read_config_regs(struct target *target) { diff --git a/src/target/mips32.h b/src/target/mips32.h index 81b6d649d8..3d03e98c58 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -13,6 +13,8 @@ #ifndef OPENOCD_TARGET_MIPS32_H #define OPENOCD_TARGET_MIPS32_H +#include + #include "target.h" #include "mips32_pracc.h" @@ -55,6 +57,9 @@ #define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000 +/* Insert extra NOPs after the DRET instruction on exit from debug. */ +#define EJTAG_QUIRK_PAD_DRET BIT(0) + /* offsets into mips32 core register cache */ enum { MIPS32_PC = 37, @@ -91,6 +96,11 @@ struct mips32_common { enum mips32_isa_mode isa_mode; enum mips32_isa_imp isa_imp; + /* processor identification register */ + uint32_t prid; + /* CPU specific quirks */ + uint32_t cpu_quirks; + /* working area for fastdata access */ struct working_area *fast_data_area; @@ -408,6 +418,8 @@ int mips32_enable_interrupts(struct target *target, int enable); int mips32_examine(struct target *target); +int mips32_cpu_probe(struct target *target); + int mips32_read_config_regs(struct target *target); int mips32_register_commands(struct command_context *cmd_ctx); diff --git a/src/target/mips_cpu.h b/src/target/mips_cpu.h new file mode 100644 index 0000000000..8190b32e43 --- /dev/null +++ b/src/target/mips_cpu.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef OPENOCD_TARGET_MIPS_CPU_H +#define OPENOCD_TARGET_MIPS_CPU_H + +/* + * NOTE: The proper detection of certain CPUs can become quite complicated. + * Please consult the following Linux kernel code when adding new CPUs: + * arch/mips/include/asm/cpu.h + * arch/mips/kernel/cpu-probe.c + */ + +/* Assigned Company values for bits 23:16 of the PRId register. */ +#define PRID_COMP_MASK 0xff0000 + +#define PRID_COMP_LEGACY 0x000000 +#define PRID_COMP_INGENIC_E1 0xe10000 + +/* + * Assigned Processor ID (implementation) values for bits 15:8 of the PRId + * register. In order to detect a certain CPU type exactly eventually additional + * registers may need to be examined. + */ +#define PRID_IMP_MASK 0xff00 + +#define PRID_IMP_XBURST_REV1 0x0200 /* XBurst®1 with MXU1.0/MXU1.1 SIMD ISA */ + +#endif /* OPENOCD_TARGET_MIPS_CPU_H */ diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index a1a179216d..5c92bf9ee3 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -259,9 +259,12 @@ int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info) { struct pa_list pracc_list = {.instr = MIPS32_DRET(ejtag_info->isa), .addr = 0}; struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = &pracc_list, .code_count = 1, .store_count = 0}; + struct mips32_common *mips32 = container_of(ejtag_info, + struct mips32_common, ejtag_info); /* execute our dret instruction */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 0); /* shift out instr, omit last check */ + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, + mips32->cpu_quirks & EJTAG_QUIRK_PAD_DRET); /* pic32mx workaround, false pending at low core clock */ jtag_add_sleep(1000); diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 14e3f3b27a..46d241cb30 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -100,6 +100,8 @@ static int mips_m4k_debug_entry(struct target *target) /* attempt to find halt reason */ mips_m4k_examine_debug_reason(target); + mips32_cpu_probe(target); + mips32_read_config_regs(target); /* default to mips32 isa, it will be changed below if required */ From aa0056d27355d7719a120cdc4292215acae40819 Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Wed, 16 Aug 2023 17:01:10 +0200 Subject: [PATCH 13/50] jtag/drivers: add new VIDs for angie driver - add a check for a returned value add a line that checks the returned value of set signals function add two VIDs of other original boards (have onboard angie architecture) so angie driver can connect to them and change their VID after renumeration. Change-Id: Ide4f1f6f38168a410191bf3ff75bcd59dcf7ef50 Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/7795 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/60-openocd.rules | 2 ++ src/jtag/drivers/angie.c | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index fd88564bdc..b0e229d07f 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -226,6 +226,8 @@ ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1002", MODE="660", GROUP="plugdev", # ANGIE USB-JTAG Adapter ATTRS{idVendor}=="584e", ATTRS{idProduct}=="424e", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4255", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4355", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4a55", MODE="660", GROUP="plugdev", TAG+="uaccess" # Marvell Sheevaplug diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index 35811fb80c..9cc086599c 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -30,8 +30,10 @@ /** USB Product ID of ANGIE device in unconfigured state (no firmware loaded * yet) or with its firmware. */ -#define ANGIE_PID 0x424e -#define ANGIE_PID_2 0x4a55 +#define ANGIE_PID 0x424e +#define ANGIE_PID_2 0x4255 +#define ANGIE_PID_3 0x4355 +#define ANGIE_PID_4 0x4a55 /** Address of EZ-USB ANGIE CPU Control & Status register. This register can be * written by issuing a Control EP0 vendor request. */ @@ -252,8 +254,8 @@ static struct angie *angie_handle; static int angie_usb_open(struct angie *device) { struct libusb_device_handle *usb_device_handle; - const uint16_t vids[] = {ANGIE_VID, ANGIE_VID, 0}; - const uint16_t pids[] = {ANGIE_PID, ANGIE_PID_2, 0}; + const uint16_t vids[] = {ANGIE_VID, ANGIE_VID, ANGIE_VID, ANGIE_VID, 0}; + const uint16_t pids[] = {ANGIE_PID, ANGIE_PID_2, ANGIE_PID_3, ANGIE_PID_4, 0}; int ret = jtag_libusb_open(vids, pids, &usb_device_handle, NULL); @@ -1719,6 +1721,8 @@ static int angie_reset(int trst, int srst) high |= SIGNAL_SRST; int ret = angie_append_set_signals_cmd(device, low, high); + if (ret == ERROR_OK) + angie_clear_queue(device); ret = angie_execute_queued_commands(device, LIBUSB_TIMEOUT_MS); if (ret == ERROR_OK) From aee495e7859d0f19b52ba12cafaad2628d84f8e1 Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Wed, 16 Aug 2023 17:05:05 +0200 Subject: [PATCH 14/50] contrib/firmware: add new i2c bit-banging feature to angie's firmware add new i2c bit-banging feature, we can now connect in JTAG with the SoC target and in i2c with the main board components at the same time. Change-Id: I8e4516fe1ad5238e0373444f1c3c9bc0814d0f52 Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/7796 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/firmware/angie/c/Makefile | 7 +- contrib/firmware/angie/c/README | 4 +- contrib/firmware/angie/c/include/i2c.h | 28 +++ contrib/firmware/angie/c/include/io.h | 16 +- contrib/firmware/angie/c/include/usb.h | 120 +++++----- contrib/firmware/angie/c/src/i2c.c | 127 ++++++++++ contrib/firmware/angie/c/src/protocol.c | 13 +- contrib/firmware/angie/c/src/usb.c | 217 ++++++++++++++---- contrib/firmware/angie/hdl/Makefile | 2 +- ...{angie_openocd.ucf => angie_bitstream.ucf} | 16 +- ...{angie_openocd.vhd => angie_bitstream.vhd} | 64 ++++-- doc/usb_adapters/angie/584e_424e_angie.txt | 59 ++++- src/jtag/drivers/angie/angie_bitstream.bit | Bin 340702 -> 340704 bytes src/jtag/drivers/angie/angie_firmware.bin | Bin 9298 -> 10158 bytes 14 files changed, 534 insertions(+), 139 deletions(-) create mode 100644 contrib/firmware/angie/c/include/i2c.h create mode 100644 contrib/firmware/angie/c/src/i2c.c rename contrib/firmware/angie/hdl/src/{angie_openocd.ucf => angie_bitstream.ucf} (83%) rename contrib/firmware/angie/hdl/src/{angie_openocd.vhd => angie_bitstream.vhd} (55%) diff --git a/contrib/firmware/angie/c/Makefile b/contrib/firmware/angie/c/Makefile index 80e8cbe57b..e919cd0114 100644 --- a/contrib/firmware/angie/c/Makefile +++ b/contrib/firmware/angie/c/Makefile @@ -38,7 +38,7 @@ LDFLAGS = --code-loc 0x0000 --code-size $(CODE_SIZE) --xram-loc $(XRAM_LOC) \ --xram-size $(XRAM_SIZE) --iram-size 256 --model-small # list of base object files -OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel serial.rel gpif.rel +OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel serial.rel gpif.rel i2c.rel HEADERS = $(INCLUDE_DIR)/usb.h \ $(INCLUDE_DIR)/protocol.h \ $(INCLUDE_DIR)/jtag.h \ @@ -47,7 +47,8 @@ HEADERS = $(INCLUDE_DIR)/usb.h \ $(INCLUDE_DIR)/io.h \ $(INCLUDE_DIR)/serial.h \ $(INCLUDE_DIR)/fx2macros.h \ - $(INCLUDE_DIR)/msgtypes.h + $(INCLUDE_DIR)/msgtypes.h \ + $(INCLUDE_DIR)/i2c.h # Disable all built-in rules. .SUFFIXES: @@ -61,7 +62,7 @@ all: angie_firmware.ihx angie_firmware.ihx: $(OBJECTS) $(CC) -mmcs51 $(LDFLAGS) -o $@ $^ -# Rebuild every C module (there are only 5 of them) if any header changes. +# Rebuild every C module (there are only 8 of them) if any header changes. %.rel: $(SRC_DIR)/%.c $(HEADERS) $(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $< diff --git a/contrib/firmware/angie/c/README b/contrib/firmware/angie/c/README index 04ed0be2ac..2d41da7a40 100644 --- a/contrib/firmware/angie/c/README +++ b/contrib/firmware/angie/c/README @@ -12,8 +12,8 @@ To compile the firmware, the SDCC compiler package is required. Most Linux distributions include SDCC in their official package repositories. The SDCC source code can be found at http://sdcc.sourceforge.net/ -Simply type "make hex" in the ANGIE directory to compile the firmware. -"make clean" will remove all generated files except the Intel HEX file +Simply type "make bin" in the ANGIE directory to compile the firmware. +"make clean" will remove all generated files except the BIN file required for downloading the firmware to ANGIE. Note that the EZ-USB FX2 microcontroller does not have on-chip flash, diff --git a/contrib/firmware/angie/c/include/i2c.h b/contrib/firmware/angie/c/include/i2c.h new file mode 100644 index 0000000000..06185efb4d --- /dev/null +++ b/contrib/firmware/angie/c/include/i2c.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/**************************************************************************** + File : i2c.h * + Contents : i2c bit-bang library * + Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. * + * + * +*****************************************************************************/ + +#ifndef __I2C_H +#define __I2C_H + +#include +#include +#include + +void start_cd(void); +void repeated_start(void); +void stop_cd(void); +void clock_cd(void); +void send_ack(void); +bool get_ack(void); + +uint8_t get_address(uint8_t adr, uint8_t rdwr); + +void send_byte(uint8_t input); +uint8_t receive_byte(void); +#endif diff --git a/contrib/firmware/angie/c/include/io.h b/contrib/firmware/angie/c/include/io.h index 35afa626f7..af488f4ed9 100644 --- a/contrib/firmware/angie/c/include/io.h +++ b/contrib/firmware/angie/c/include/io.h @@ -45,14 +45,14 @@ #define PIN_TDI IOB3 #define PIN_TDO IOB4 #define PIN_SRST IOB5 -/* PA6 Not Connected */ -/* PA7 Not Connected */ +/* PB6 Not Connected */ +/* PB7 Not Connected */ /* JTAG Signals with direction 'OUT' on port B */ /* PIN_TDI - PIN_TCK - PIN_TMS - PIN_TRST - PIN_SRST */ #define MASK_PORTB_DIRECTION_OUT (bmbit0 | bmbit1 | bmbit2 | bmbit3 | bmbit5) -/* PORT C */ // Debug: +/* PORT C */ #define PIN_T0 IOC0 #define PIN_T1 IOC1 #define PIN_T2 IOC2 @@ -62,4 +62,14 @@ /* PC6 Not Connected */ /* PC7 Not Connected */ +/* PORT D */ +#define PIN_SDA IOD0 +#define PIN_SCL IOD1 +#define PIN_SDA_DIR IOD2 +/* PD3 Not Connected */ +/* PD4 Not Connected */ +/* PD5 Not Connected */ +/* PD6 Not Connected */ +/* PD7 Not Connected */ + #endif diff --git a/contrib/firmware/angie/c/include/usb.h b/contrib/firmware/angie/c/include/usb.h index 0450d1d1c9..07cb12ae6a 100644 --- a/contrib/firmware/angie/c/include/usb.h +++ b/contrib/firmware/angie/c/include/usb.h @@ -24,18 +24,19 @@ #define STALL_EP0() (EP0CS |= EPSTALL) #define CLEAR_IRQ() (USBINT = 0) -/*********** USB descriptors. See section 9.5 of the USB 1.1 spec **********/ +/*********** USB descriptors. See USB 2.0 Spec **********/ -/* USB Descriptor Types. See USB 1.1 spec, page 187, table 9-5 */ -#define DESCRIPTOR_TYPE_DEVICE 0x01 -#define DESCRIPTOR_TYPE_CONFIGURATION 0x02 -#define DESCRIPTOR_TYPE_STRING 0x03 -#define DESCRIPTOR_TYPE_INTERFACE 0x04 -#define DESCRIPTOR_TYPE_ENDPOINT 0x05 +/* USB Descriptor Types. See USB 2.0 Spec */ +#define DESCRIPTOR_TYPE_DEVICE 0x01 +#define DESCRIPTOR_TYPE_CONFIGURATION 0x02 +#define DESCRIPTOR_TYPE_STRING 0x03 +#define DESCRIPTOR_TYPE_INTERFACE 0x04 +#define DESCRIPTOR_TYPE_ENDPOINT 0x05 +#define DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0B #define STR_DESCR(len, ...) { (len) * 2 + 2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } } -/** USB Device Descriptor. See USB 1.1 spec, pp. 196 - 198 */ +/** USB Device Descriptor. See USB 2.0 Spec */ struct usb_device_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< DEVICE Descriptor Type. */ @@ -53,7 +54,7 @@ struct usb_device_descriptor { uint8_t bnumconfigurations; /**< Number of possible configurations. */ }; -/** USB Configuration Descriptor. See USB 1.1 spec, pp. 199 - 200 */ +/** USB Configuration Descriptor. See USB 2.0 Spec */ struct usb_config_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< CONFIGURATION descriptor type. */ @@ -65,7 +66,19 @@ struct usb_config_descriptor { uint8_t maxpower; /**< Maximum power consumption in 2 mA units. */ }; -/** USB Interface Descriptor. See USB 1.1 spec, pp. 201 - 203 */ +/** USB Interface association Descriptor. See USB 2.0 Spec */ +struct usb_interface_association_descriptor { + uint8_t blength; + uint8_t bdescriptortype; + uint8_t bfirstinterface; + uint8_t binterfacecount; + uint8_t bfunctionclass; + uint8_t bfunctionsubclass; + uint8_t bfunctionprotocol; + uint8_t ifunction; +}; + +/** USB Interface Descriptor. See USB 2.0 Spec */ struct usb_interface_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< INTERFACE descriptor type. */ @@ -78,7 +91,7 @@ struct usb_interface_descriptor { uint8_t iinterface; /**< Index of interface string descriptor. */ }; -/** USB Endpoint Descriptor. See USB 1.1 spec, pp. 203 - 204 */ +/** USB Endpoint Descriptor. See USB 2.0 Spec */ struct usb_endpoint_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< ENDPOINT descriptor type. */ @@ -88,14 +101,14 @@ struct usb_endpoint_descriptor { uint8_t binterval; /**< Polling interval (in ms) for this endpoint. */ }; -/** USB Language Descriptor. See USB 1.1 spec, pp. 204 - 205 */ +/** USB Language Descriptor. See USB 2.0 Spec */ struct usb_language_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< STRING descriptor type. */ uint16_t wlangid[]; /**< LANGID codes. */ }; -/** USB String Descriptor. See USB 1.1 spec, pp. 204 - 205 */ +/** USB String Descriptor. See USB 2.0 Spec */ struct usb_string_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< STRING descriptor type. */ @@ -104,7 +117,7 @@ struct usb_string_descriptor { /********************** USB Control Endpoint 0 related *********************/ -/** USB Control Setup Data. See USB 1.1 spec, pp. 183 - 185 */ +/** USB Control Setup Data. See USB 2.0 Spec */ struct setup_data { uint8_t bmrequesttype; /**< Characteristics of a request. */ uint8_t brequest; /**< Specific request. */ @@ -121,66 +134,66 @@ extern volatile bool ep1_in; extern volatile __xdata __at 0xE6B8 struct setup_data setup_data; /* - * USB Request Types (bmRequestType): See USB 1.1 spec, page 183, table 9-2 + * USB Request Types (bmRequestType): See USB 2.0 Spec * * Bit 7: Data transfer direction - * 0 = Host-to-device - * 1 = Device-to-host + * 0 = Host-to-device + * 1 = Device-to-host * Bit 6...5: Type - * 0 = Standard - * 1 = Class - * 2 = Vendor - * 3 = Reserved + * 0 = Standard + * 1 = Class + * 2 = Vendor + * 3 = Reserved * Bit 4...0: Recipient - * 0 = Device - * 1 = Interface - * 2 = Endpoint - * 3 = Other - * 4...31 = Reserved + * 0 = Device + * 1 = Interface + * 2 = Endpoint + * 3 = Other + * 4...31 = Reserved */ -#define USB_DIR_OUT 0x00 -#define USB_DIR_IN 0x80 +#define USB_DIR_OUT 0x00 +#define USB_DIR_IN 0x80 #define USB_REQ_TYPE_STANDARD (0x00 << 5) #define USB_REQ_TYPE_CLASS (0x01 << 5) #define USB_REQ_TYPE_VENDOR (0x02 << 5) #define USB_REQ_TYPE_RESERVED (0x03 << 5) -#define USB_RECIP_DEVICE 0x00 -#define USB_RECIP_INTERFACE 0x01 -#define USB_RECIP_ENDPOINT 0x02 -#define USB_RECIP_OTHER 0x03 +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 /* Clear Interface Request */ -#define CF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define CF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) #define CF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) #define CF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) /* Get Configuration Request */ -#define GC_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define GC_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Get Descriptor Request */ -#define GD_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define GD_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Get Interface Request */ #define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) /* Get Status Request: See USB 1.1 spec, page 190 */ -#define GS_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define GS_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) #define GS_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) #define GS_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) /* Set Address Request is handled by EZ-USB core */ /* Set Configuration Request */ -#define SC_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define SC_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Set Descriptor Request */ -#define SD_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define SD_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Set Feature Request */ -#define SF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define SF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) #define SF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) #define SF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) @@ -190,27 +203,27 @@ extern volatile __xdata __at 0xE6B8 struct setup_data setup_data; /* Synch Frame Request */ #define SY_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) -/* USB Requests (bRequest): See USB 1.1 spec, table 9-4 on page 187 */ -#define GET_STATUS 0 -#define CLEAR_FEATURE 1 +/* USB Requests (bRequest): See USB 2.0 Spec */ +#define GET_STATUS 0 +#define CLEAR_FEATURE 1 /* Value '2' is reserved for future use */ -#define SET_FEATURE 3 +#define SET_FEATURE 3 /* Value '4' is reserved for future use */ -#define SET_ADDRESS 5 -#define GET_DESCRIPTOR 6 -#define SET_DESCRIPTOR 7 -#define GET_CONFIGURATION 8 -#define SET_CONFIGURATION 9 +#define SET_ADDRESS 5 +#define GET_DESCRIPTOR 6 +#define SET_DESCRIPTOR 7 +#define GET_CONFIGURATION 8 +#define SET_CONFIGURATION 9 #define GET_INTERFACE 10 #define SET_INTERFACE 11 #define SYNCH_FRAME 12 -/* Standard Feature Selectors: See USB 1.1 spec, table 9-6 on page 188 */ -#define DEVICE_REMOTE_WAKEUP 1 -#define ENDPOINT_HALT 0 +/* Standard Feature Selectors: See USB 2.0 Spec */ +#define DEVICE_REMOTE_WAKEUP 1 +#define ENDPOINT_HALT 0 /************************** EZ-USB specific stuff **************************/ -/** USB Interrupts. See AN2131-TRM, page 9-4 for details */ +/** USB Interrupts. See EZ-USB FX2-TRM, for details */ enum usb_isr { SUDAV_ISR = 13, SOF_ISR, @@ -265,7 +278,10 @@ bool usb_handle_set_feature(void); bool usb_handle_get_descriptor(void); void usb_handle_set_interface(void); void usb_handle_setup_data(void); +void usb_handle_i2c_in(void); +void usb_handle_i2c_out(void); +void i2c_recieve(void); void ep_init(void); void interrupt_init(void); void io_init(void); diff --git a/contrib/firmware/angie/c/src/i2c.c b/contrib/firmware/angie/c/src/i2c.c new file mode 100644 index 0000000000..a7004bfac9 --- /dev/null +++ b/contrib/firmware/angie/c/src/i2c.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/**************************************************************************** + File : i2c.cpp * + Contents : i2c bit-bang library * + Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. * + * + * +*****************************************************************************/ + +#include "i2c.h" +#include "io.h" +#include "delay.h" +#include "reg_ezusb.h" + +void start_cd(void) +{ + PIN_SDA = 0; //SDA = 1; + delay_us(1); + PIN_SCL = 0; //SCL = 1; + delay_us(1); +} + +void repeated_start(void) +{ + PIN_SDA = 1; + delay_us(1); + PIN_SCL = 1; + delay_us(1); + PIN_SDA = 0; + delay_us(1); + PIN_SCL = 0; + delay_us(1); +} + +void stop_cd(void) +{ + PIN_SDA = 0; + delay_us(1); + PIN_SCL = 1; + delay_us(1); + PIN_SDA = 1; + delay_us(1); +} + +void clock_cd(void) +{ + PIN_SCL = 1; + delay_us(1); + PIN_SCL = 0; + delay_us(1); +} + +void send_ack(void) +{ + PIN_SDA = 0; + delay_us(1); + PIN_SCL = 1; + delay_us(1); + PIN_SCL = 0; + delay_us(1); +} + +bool get_ack(void) +{ + PIN_SDA_DIR = 1; + delay_us(1); + OED = 0xFE; + PIN_SCL = 1; + delay_us(1); + bool ack = PIN_SDA; + PIN_SCL = 0; + delay_us(1); + OED = 0xFF; + PIN_SDA_DIR = 0; + delay_us(1); + return ack; +} + +/* here address(8 bits) = adr (7 bits) + type (1 bit) */ +uint8_t get_address(uint8_t adr, uint8_t rdwr) +{ + adr &= 0x7F; + adr = adr << 1; + adr |= (rdwr & 0x01); + return adr; +} + +/* here send bit after bit and clocking scl with each bit */ +void send_byte(uint8_t input) +{ + for (uint8_t i = 0; i < 8; i++) { + if ((input & 0x80)) { + PIN_SDA = 1; + delay_us(1); + clock_cd(); + } else { + PIN_SDA = 0; + delay_us(1); + clock_cd(); + } + input = input << 1; + } +} + +/* here receive bit after bit and clocking scl with each bit */ + +uint8_t receive_byte(void) +{ + PIN_SDA_DIR = 1; //FX2 <-- FPGA + OED = 0xFE; + uint8_t input = 0x00; + for (uint8_t i = 0; i < 8; i++) { + PIN_SCL = 1; + delay_us(1); + input = input << 1; + if (PIN_SDA == 1) + input |= 0x01; + else + input |= 0X00; + + PIN_SCL = 0; + delay_us(1); + } + OED = 0xFF; + PIN_SDA_DIR = 0; + return input; +} diff --git a/contrib/firmware/angie/c/src/protocol.c b/contrib/firmware/angie/c/src/protocol.c index 3f3aaaf362..d84534bf2f 100644 --- a/contrib/firmware/angie/c/src/protocol.c +++ b/contrib/firmware/angie/c/src/protocol.c @@ -139,15 +139,12 @@ bool execute_command(void) payload_index_in += usb_in_bytecount; /* Determine if this was the last command */ - if ((cmd_id_index + usb_out_bytecount + 1) >= EP1OUTBC) { + if ((cmd_id_index + usb_out_bytecount + 1) >= EP1OUTBC) return true; - /* Line between return and else required by checkpatch: */ - uint8_t a = 0; - } else { - /* Not the last command, update cmd_id_index */ - cmd_id_index += (usb_out_bytecount + 1); - return false; - } + + /* Not the last command, update cmd_id_index */ + cmd_id_index += (usb_out_bytecount + 1); + return false; } /** diff --git a/contrib/firmware/angie/c/src/usb.c b/contrib/firmware/angie/c/src/usb.c index 8fd4de6373..747fef1246 100644 --- a/contrib/firmware/angie/c/src/usb.c +++ b/contrib/firmware/angie/c/src/usb.c @@ -18,6 +18,7 @@ #include #include #include +#include "i2c.h" /* Also update external declarations in "include/usb.h" if making changes to * these variables! @@ -36,9 +37,9 @@ __code struct usb_device_descriptor device_descriptor = { .blength = sizeof(struct usb_device_descriptor), .bdescriptortype = DESCRIPTOR_TYPE_DEVICE, .bcdusb = 0x0200, /* BCD: 02.00 (Version 2.0 USB spec) */ - .bdeviceclass = 0xFF, /* 0xFF = vendor-specific */ - .bdevicesubclass = 0xFF, - .bdeviceprotocol = 0xFF, + .bdeviceclass = 0xEF, + .bdevicesubclass = 0x02, + .bdeviceprotocol = 0x01, .bmaxpacketsize0 = 64, .idvendor = 0x584e, .idproduct = 0x424e, @@ -55,25 +56,36 @@ __code struct usb_config_descriptor config_descriptor = { .blength = sizeof(struct usb_config_descriptor), .bdescriptortype = DESCRIPTOR_TYPE_CONFIGURATION, .wtotallength = sizeof(struct usb_config_descriptor) + - sizeof(struct usb_interface_descriptor) + - (NUM_ENDPOINTS * sizeof(struct usb_endpoint_descriptor)), - .bnuminterfaces = 1, + 3 * sizeof(struct usb_interface_descriptor) + + ((NUM_ENDPOINTS + 2) * sizeof(struct usb_endpoint_descriptor)), + .bnuminterfaces = 2, .bconfigurationvalue = 1, - .iconfiguration = 4, /* String describing this configuration */ + .iconfiguration = 1, /* String describing this configuration */ .bmattributes = 0x80, /* Only MSB set according to USB spec */ .maxpower = 50 /* 100 mA */ }; +__code struct usb_interface_association_descriptor interface_association_descriptor = { + .blength = sizeof(struct usb_interface_association_descriptor), + .bdescriptortype = DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, + .bfirstinterface = 0x01, + .binterfacecount = 0x02, + .bfunctionclass = 0x02, + .bfunctionsubclass = 0x00, + .bfunctionprotocol = 0x00, + .ifunction = 0x00 +}; + __code struct usb_interface_descriptor interface_descriptor00 = { .blength = sizeof(struct usb_interface_descriptor), .bdescriptortype = DESCRIPTOR_TYPE_INTERFACE, .binterfacenumber = 0, .balternatesetting = 0, .bnumendpoints = NUM_ENDPOINTS, - .binterfaceclass = 0xFF, - .binterfacesubclass = 0xFF, - .binterfaceprotocol = 0xFF, - .iinterface = 0 + .binterfaceclass = 0XFF, + .binterfacesubclass = 0x00, + .binterfaceprotocol = 0x00, + .iinterface = 4 }; __code struct usb_endpoint_descriptor bulk_ep1_out_endpoint_descriptor = { @@ -103,16 +115,19 @@ __code struct usb_endpoint_descriptor bulk_ep2_endpoint_descriptor = { .binterval = 0 }; -__code struct usb_endpoint_descriptor bulk_ep4_endpoint_descriptor = { - .blength = sizeof(struct usb_endpoint_descriptor), - .bdescriptortype = 0x05, - .bendpointaddress = (4 | USB_DIR_IN), - .bmattributes = 0x02, - .wmaxpacketsize = 512, - .binterval = 0 +__code struct usb_interface_descriptor interface_descriptor01 = { + .blength = sizeof(struct usb_interface_descriptor), + .bdescriptortype = DESCRIPTOR_TYPE_INTERFACE, + .binterfacenumber = 1, + .balternatesetting = 0, + .bnumendpoints = 2, + .binterfaceclass = 0x0A, + .binterfacesubclass = 0x00, + .binterfaceprotocol = 0x00, + .iinterface = 0x00 }; -__code struct usb_endpoint_descriptor bulk_ep6_endpoint_descriptor = { +__code struct usb_endpoint_descriptor bulk_ep6_out_endpoint_descriptor = { .blength = sizeof(struct usb_endpoint_descriptor), .bdescriptortype = 0x05, .bendpointaddress = (6 | USB_DIR_OUT), @@ -121,19 +136,18 @@ __code struct usb_endpoint_descriptor bulk_ep6_endpoint_descriptor = { .binterval = 0 }; -__code struct usb_endpoint_descriptor bulk_ep8_endpoint_descriptor = { +__code struct usb_endpoint_descriptor bulk_ep8_in_endpoint_descriptor = { .blength = sizeof(struct usb_endpoint_descriptor), .bdescriptortype = 0x05, - .bendpointaddress = (8 | USB_DIR_OUT), + .bendpointaddress = (8 | USB_DIR_IN), .bmattributes = 0x02, .wmaxpacketsize = 512, .binterval = 0 }; - __code struct usb_language_descriptor language_descriptor = { .blength = 4, .bdescriptortype = DESCRIPTOR_TYPE_STRING, - .wlangid = {0x0409 /* US English */} + .wlangid = {0x0409} /* US English */ }; __code struct usb_string_descriptor strmanufacturer = @@ -212,9 +226,15 @@ void ep4_isr(void)__interrupt EP4_ISR } void ep6_isr(void)__interrupt EP6_ISR { + i2c_recieve(); + EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */ + EPIRQ = 0x40; /* Clear individual EP6OUT IRQ */ + } void ep8_isr(void)__interrupt EP8_ISR { + EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */ + EPIRQ = 0x80; /* Clear individual EP8IN IRQ */ } void ibn_isr(void)__interrupt IBN_ISR { @@ -411,21 +431,21 @@ bool usb_handle_clear_feature(void) switch (setup_data.bmrequesttype) { case CF_DEVICE: /* Clear remote wakeup not supported: stall EP0 */ - STALL_EP0(); - break; + STALL_EP0(); + break; case CF_ENDPOINT: - if (setup_data.wvalue == 0) { + if (setup_data.wvalue == 0) { /* Unstall the endpoint specified in wIndex */ - ep_cs = usb_get_endpoint_cs_reg(setup_data.windex); - if (!ep_cs) - return false; - *ep_cs &= ~EPSTALL; + ep_cs = usb_get_endpoint_cs_reg(setup_data.windex); + if (!ep_cs) + return false; + *ep_cs &= ~EPSTALL; } else { /* Unsupported feature, stall EP0 */ - STALL_EP0(); - } - break; - default: + STALL_EP0(); + } + break; + default: /* Vendor commands... */ break; } @@ -597,7 +617,6 @@ bool usb_handle_send_bitstream(void) /* wait until GPIF transaction has been completed */ while ((GPIFTRIG & BMGPIFDONE) == 0) { if (ix-- == 0) { - printf("GPIF done time out\n"); break; } delay_ms(1); @@ -697,9 +716,9 @@ void ep_init(void) syncdelay(3); EP4CFG = 0x00; syncdelay(3); - EP6CFG = 0x00; + EP6CFG = 0xA2; syncdelay(3); - EP8CFG = 0x00; + EP8CFG = 0xE2; syncdelay(3); /* arm EP1-OUT */ @@ -714,6 +733,12 @@ void ep_init(void) EP1INBC = 0; syncdelay(3); + /* arm EP6-OUT */ + EP6BCL = 0x80; + syncdelay(3); + EP6BCL = 0x80; + syncdelay(3); + /* Standard procedure to reset FIFOs */ FIFORESET = BMNAKALL; /* NAK all transfers during the reset */ syncdelay(3); @@ -727,9 +752,110 @@ void ep_init(void) syncdelay(3); } +void i2c_recieve(void) +{ + PIN_SDA_DIR = 0; + if (EP6FIFOBUF[0] == 1) { + uint8_t rdwr = EP6FIFOBUF[0]; //read + uint8_t reg_adr_check = EP6FIFOBUF[1]; + uint8_t count = EP6FIFOBUF[2]; //request data count + uint8_t adr = EP6FIFOBUF[3]; //address + uint8_t reg_adr = EP6FIFOBUF[4]; + uint8_t address = get_address(adr, rdwr); //address byte (read command) + uint8_t address_2 = get_address(adr, 0); //address byte 2 (write command) + + printf("%d\n", address); + + /* start: */ + start_cd(); + /* address: */ + send_byte(address_2); //write + /* ack: */ + uint8_t ack = get_ack(); + + delay_us(10); + + /* send data */ + if (reg_adr_check) { //if there is a byte reg + send_byte(reg_adr); + /* ack(): */ + ack = get_ack(); + } + + delay_us(10); + + /* repeated start: */ + repeated_start(); + /* address: */ + send_byte(address); + /* get ack: */ + ack = get_ack(); + + delay_us(10); + + /* receive data */ + for (uint8_t i = 0; i < count; i++) { + EP8FIFOBUF[i] = receive_byte(); + + /* send ack: */ + send_ack(); + } + + delay_ms(1); + + /* stop */ + stop_cd(); + + delay_us(10); + + EP8BCH = 0; //EP8 + syncdelay(3); + EP8BCL = count; //EP8 + + EP6BCL = 0x80; //EP6 + syncdelay(3); + EP6BCL = 0x80; //EP6 + } else { + uint8_t rdwr = EP6FIFOBUF[0]; //write + uint8_t count = EP6FIFOBUF[1]; //data count + uint8_t adr = EP6FIFOBUF[2]; //address + uint8_t address = get_address(adr, rdwr); //address byte (read command) + uint8_t ack_cnt = 0; + +/* start(): */ + start_cd(); +/* address: */ + send_byte(address); //write +/* ack(): */ + if (!get_ack()) + ack_cnt++; +/* send data */ + for (uint8_t i = 0; i < count; i++) { + send_byte(EP6FIFOBUF[i + 3]); + + /* get ack: */ + if (!get_ack()) + ack_cnt++; + } + +/* stop */ + stop_cd(); + + EP8FIFOBUF[0] = ack_cnt; + + EP8BCH = 0; //EP8 + syncdelay(3); + EP8BCL = 1; //EP8 + + EP6BCL = 0x80; //EP6 + syncdelay(3); + EP6BCL = 0x80; //EP6 + } +} + /** * Interrupt initialization. Configures USB interrupts. - */ + **/ void interrupt_init(void) { /* Enable Interrupts */ @@ -742,11 +868,11 @@ void interrupt_init(void) /* Enable INT 2 & 4 Autovectoring */ INTSETUP |= (AV2EN | AV4EN); - /* Enable individual EP1OUT&IN interrupts */ - EPIE |= 0x0C; + /* Enable individual EP1OUT&IN & EP6&8 interrupts */ + EPIE |= 0xCC; /* Clear individual USB interrupt IRQ */ - EPIRQ = 0x0C; + EPIRQ = 0xCC; /* Enable SUDAV interrupt */ USBIEN |= SUDAVI; @@ -777,8 +903,15 @@ void io_init(void) PIN_TDI = 0; PIN_SRST = 1; + + /* PORT C */ PORTCCFG = 0x00; /* 0: normal ou 1: alternate function (each bit) */ - OEC = 0xEF; + OEC = 0xFF; IOC = 0xFF; + + /* PORT D */ + OED = 0xFF; + IOD = 0xFF; + PIN_SDA_DIR = 0; } diff --git a/contrib/firmware/angie/hdl/Makefile b/contrib/firmware/angie/hdl/Makefile index c2c74a0b80..b28b650892 100644 --- a/contrib/firmware/angie/hdl/Makefile +++ b/contrib/firmware/angie/hdl/Makefile @@ -2,7 +2,7 @@ # Copyright (C) 2023 by NanoXplore, France - all rights reserved # Needed by timing test -export PROJECT := angie_openocd +export PROJECT := angie_bitstream TARGET_PART := xc6slx9-2tqg144 export TOPLEVEL := S609 diff --git a/contrib/firmware/angie/hdl/src/angie_openocd.ucf b/contrib/firmware/angie/hdl/src/angie_bitstream.ucf similarity index 83% rename from contrib/firmware/angie/hdl/src/angie_openocd.ucf rename to contrib/firmware/angie/hdl/src/angie_bitstream.ucf index fda3cdaaf1..92a89c99e1 100644 --- a/contrib/firmware/angie/hdl/src/angie_openocd.ucf +++ b/contrib/firmware/angie/hdl/src/angie_bitstream.ucf @@ -14,17 +14,31 @@ net TRST LOC = 'P48' ; net TMS LOC = 'P43' ; net TCK LOC = 'P44' ; net TDI LOC = 'P45' ; -net TDO LOC = 'P46' ; +net TDO LOC = 'P46' ; net SRST LOC = 'P61' ; + +net SDA LOC = 'P50' ; +net SCL LOC = 'P51' ; +net SDA_DIR LOC = 'P56' ; + net SI_TDO LOC = 'P16' ; net SO_TRST LOC = 'P32' ; net SO_TMS LOC = 'P27' ; net SO_TCK LOC = 'P30' ; net SO_TDI LOC = 'P26' ; net SO_SRST LOC = 'P12' ; + +net SO_SDA_OUT LOC = 'P140' ; +net SO_SDA_IN LOC = 'P1' ; +net SO_SCL LOC = 'P137'; + net ST_0 LOC = 'P29' ; net ST_1 LOC = 'P21' ; net ST_2 LOC = 'P11' ; + +net ST_4 LOC = 'P134' ; +net ST_5 LOC = 'P139' ; + net FTP<0> LOC = 'P121' ; net FTP<1> LOC = 'P120' ; net FTP<2> LOC = 'P119' ; diff --git a/contrib/firmware/angie/hdl/src/angie_openocd.vhd b/contrib/firmware/angie/hdl/src/angie_bitstream.vhd similarity index 55% rename from contrib/firmware/angie/hdl/src/angie_openocd.vhd rename to contrib/firmware/angie/hdl/src/angie_bitstream.vhd index d79c0fecef..21ddb844af 100644 --- a/contrib/firmware/angie/hdl/src/angie_openocd.vhd +++ b/contrib/firmware/angie/hdl/src/angie_bitstream.vhd @@ -16,22 +16,35 @@ library UNISIM; use UNISIM.VComponents.all; entity S609 is port( - TRST : in std_logic; - TMS : in std_logic; - TCK : in std_logic; - TDI : in std_logic; - TDO : out std_logic; - SRST : in std_logic; - FTP : out std_logic_vector(7 downto 0); -- Test points + TRST : in std_logic; + TMS : in std_logic; + TCK : in std_logic; + TDI : in std_logic; + TDO : out std_logic; + SRST : in std_logic; + + SDA : inout std_logic; + SDA_DIR : in std_logic; + SCL : in std_logic; + + FTP : out std_logic_vector(7 downto 0):=(others => '1'); -- Test points SI_TDO : in std_logic; - ST_0 : out std_logic; - ST_1 : out std_logic; - ST_2 : out std_logic; + ST_0 : out std_logic; + ST_1 : out std_logic; + ST_2 : out std_logic; + + ST_4 : out std_logic; + ST_5 : out std_logic; + + SO_SDA_OUT : out std_logic; + SO_SDA_IN : in std_logic; + SO_SCL : out std_logic; + SO_TRST : out std_logic; - SO_TMS : out std_logic; - SO_TCK : out std_logic; + SO_TMS : out std_logic; + SO_TCK : out std_logic; SO_TDI : out std_logic; - SO_SRST :out std_logic + SO_SRST : out std_logic ); end S609; @@ -42,6 +55,8 @@ begin ST_0 <= '0'; ST_1 <= '1'; +ST_4 <= '0'; + --TDO: TDO <= not SI_TDO; @@ -53,11 +68,26 @@ SO_TDI <= TDI; ST_2 <= SRST; SO_SRST <= '0'; +SO_SCL <= SCL; + +SDA <= not(SO_SDA_IN) when (SDA_DIR = '1') else 'Z'; +SO_SDA_OUT <= SDA; + +process(SDA_DIR) +begin + if(SDA_DIR = '1') then + ST_5 <= '1'; + else + ST_5 <= '0'; + end if; +end process; + + --Points de test: -FTP(0) <= TRST; -FTP(1) <= TMS; -FTP(2) <= TCK; -FTP(3) <= TDI; +FTP(0) <= SDA; +FTP(1) <= SCL; +FTP(2) <= not(SO_SDA_IN); +FTP(3) <= SDA_DIR; FTP(5) <= SRST; FTP(4) <= SI_TDO; FTP(6) <= '1'; diff --git a/doc/usb_adapters/angie/584e_424e_angie.txt b/doc/usb_adapters/angie/584e_424e_angie.txt index 8162cbad5a..d68657a98c 100644 --- a/doc/usb_adapters/angie/584e_424e_angie.txt +++ b/doc/usb_adapters/angie/584e_424e_angie.txt @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later -Bus 001 Device 056: ID 584e:424e NanoXplore, SAS. ANGIE Adapter +Bus 001 Device 029: ID 584e:424e NanoXplore, SAS. ANGIE Adapter Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 - bDeviceClass 255 Vendor Specific Class - bDeviceSubClass 255 Vendor Specific Subclass - bDeviceProtocol 255 Vendor Specific Protocol + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 + bDeviceProtocol 1 Interface Association bMaxPacketSize0 64 idVendor 0x584e idProduct 0x424e @@ -19,13 +19,22 @@ Device Descriptor: Configuration Descriptor: bLength 9 bDescriptorType 2 - wTotalLength 0x0027 - bNumInterfaces 1 + wTotalLength 0x0047 + bNumInterfaces 2 bConfigurationValue 1 - iConfiguration 4 (error) + iConfiguration 1 NanoXplore, SAS. bmAttributes 0x80 (Bus Powered) MaxPower 100mA + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 1 + bInterfaceCount 2 + bFunctionClass 2 Communications + bFunctionSubClass 0 + bFunctionProtocol 0 + iFunction 0 Interface Descriptor: bLength 9 bDescriptorType 4 @@ -33,9 +42,9 @@ Device Descriptor: bAlternateSetting 0 bNumEndpoints 3 bInterfaceClass 255 Vendor Specific Class - bInterfaceSubClass 255 Vendor Specific Subclass - bInterfaceProtocol 255 Vendor Specific Protocol - iInterface 0 + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 4 JTAG Adapter Endpoint Descriptor: bLength 7 bDescriptorType 5 @@ -66,3 +75,33 @@ Device Descriptor: Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x06 EP 6 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x88 EP 8 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 diff --git a/src/jtag/drivers/angie/angie_bitstream.bit b/src/jtag/drivers/angie/angie_bitstream.bit index 9e83e6b69d92a880881baf8d68ab171fb1a3f09e..aebd3700b3c36cf4d1d83d7a3939a94eebcf1d41 100644 GIT binary patch delta 1559 zcmZuxU1%It6rOYM-pz@2CLZ`+?8L?*T*k>HWC(fmGxsIw z?@O2Dr4JsE;JMuu-|havVNl+ysx7?8c%_u(kMEG+&s$5Ni7F%XnL~08y!rM~d^inz ziK|N!_C4i)xcl1_FMnz!_!S@)W*V&36v(OgD~rRx!kmzdbi61u>5!nmJ}y&A*p8Qi zQ!t6&q~UQ&Q2-GwJAA59kg_~81dl?n;yil$Co(Sa>X&kY9H<1<68oBhq@RMS1 z2nZr0Rv8zCHk(M$EtK%8_{YFsHpC|Bt?4}lY?z+i2hyp@%Wm?=?OBTHsUu30#<>I) ze5s9e{1sF^!336%*3H1uMp9*c1p4Cy9J2{jmMn<_e~hntSn#Xr-XON7UPjCW3@f=% z13&M-BZ}cS#jOeAyxzb${}&vFJy%-~gP3AUSH`IO*UT#H)iTD-wSeg*%2L>5`greN+mTfO!Ik6dBhQd@6Ii)j(zC)int zX_9wNopoPj+SmA7Yhd&V7MEi27x@tm6@yzKYzbA_8HwtkD`WktS-(j>-w;jPq>8K@ zi9~A~rf2}~3py4ubB+wVlvEMbn0|Ue?zZXnxDFI)1WMubi1tcK%5t>w}TN_ z1sXmDd0c&;T&0>601jl}Eo!i>^y0D{jM4I-BA5vS-ig6i*gaE_A43arT5<6fe$fms zYijkUf{K0f_Iz_flZa~kG@TYYF{-5l&vhx+Ho-8Ab|Y~b6W!_ne{=N3dsLr*B38Rp z5g#fk$0AJd!=qc(GZ^nyk5PtQyqD4aCDkS5*26B2mR0BUyoK+URhzW;-^8!VD*rEU CAn)-2 delta 1144 zcmaJ=Pe>F|7@s$9XLn{Dbj>w)S8P|yw%Uc+*(^(>Fe-}*OgdDOj=t`H+^|G)O z5~dC{qy^GH(9_C5j}FmNm-5ubE=q{xL5Tj4oh0miZ)VNF+J*1U`~JP(@B6(szv%tA z=&j(SqHorp<4`-dt-b3?XGdFivZJf}Qerr$cxn|j#w9pOt*NU~>vr#%YJFR2B>Hhk z5253_HkLL*3g*)juZzv0g>&U*R-8bOa}i|iG_?eq*+H+9Za4c4 zS{?#ZmG>n}?Plv@EDKJWEMTzB5JJe*#sV(dq{R!7yO_)ijsP}dDgF>p`bmK+dhes1 ztQbrcm@-I^^dAl%jbGK9QX+A=Q7h85)Gg>!h|K%qGlUxSV$}RxMghqfU&f-5UB*3> z*b5#2WJvApXB?((^I~t5f+gZdhzLGaG08ZVJ8#TXSW4{nKb_ zl;05P2F|nc|IQ_4w~@ktA9Ya7<Mz$#dPC?f5xm=J>bUVBB6!G?sIZSWL+BVXPR0ZusgDT}9#>|#j4ZJ}k74E5l< zPB7RKr>c_%+dAhB(}D6$J57^f6RVzKnnVcm)wHA)o=GNuUJ~m}2aJ_AO5E6>?mJ1g z$h4Z-x4+%DyKmp#-g~-bQ{j2D+{>1nr%Zfvf3f6OMuc@ z6;+~AG?3Bx6R|){iYY4>f3KspK7~T`mq6`6UjfYm{Ril4pgEv?h3n#-ZM&K98)1XCT6#gry0@9_ek&(KIIfdr2bq&ncU`ti4js zl!QNHmh0{&CBcJjY<NrBdcd&m$G_>BsD;GhWJ6;&X(2lgE2Oyi|J+cANPnp zs*mcTEEI#NWi>XfDbp%^hW)8dzX9ogg$s4KV_-Zet5M-!3x(nZO9oE_Wy(ZarIAwR z&yhqQoKyOxfxuvbWB)uZjR(Ycs7%o}iY8P1ovNv#5mTvYrZZ2bXz=vk#Wwx=9b0B< zO@X8|Q)>+*1C!m?KAK8QwHYaU+sdcf^yFvA{5UiOtxRfq8d{Z3xH;xq4=ZwJ2Jo<+ zx2kceYx9Cu_N>PVeTfcw!qZHUj~_(rQBIc+Ve%HuRI6}$VaJvn%;n(X$pw=V;p_q~ z6+T_S1B)g(Ftn)k<=~@&f59;qvpITpp^s&iT@1tL!1VKhM?XF)&r(Y25{>)}GCoCw zBrng>N=lwZ$^&_pQSSTXSyq`JkfMf6PdN6yC6TTWc?z^_l;Irv&Py>S#vZ17DAG1j zCQ3(<@I_P+JV5@a!a2S1L$!0sLtJ@`SjKc&*F&6Roz^5_O|Op`W;!kX608Mr$)peT zda%$me3&a&V$5MFJ(qFR`=~23CtK=5Z14PHnwQdPl6Je3;2cY05WC3#5%g7551qw1 zsIcRlsJ|WFQmpt-99RAsr4tN z$yHO3$Aiwc2+g4UcO!^Frl|-6_;!Sa(Gt-ysK6Sj0{nQS8t~eP8}R-}4d9+gEsXC) z>KHgqBOVx=B3>8|MwY;MF|w3F=GDl&rcZa?f(5AiItWyfU87!G!vas`;WfA` ziyGJKCcUwABCGhuGJMJ6#2RDSNUp?(bEFbp%}9Ne4{7W2Kfsmw^<;0Epj;+*zAJ00 z!&cK$JeI!+@qL&sXnoYQc|`Jm8Mk&8%W5cY%{<J2aMG~4lGg(p$jZTw-OAMqu4hxsmH-z^Ff<;|jNgkj4sh|+HToUj6}AC%!^ zoSr6=XNvn#Z)TN@rO`6Ec-*3uO;s$lSdjYs@({CnFH#Gk~sYUgzP;&iDmWQ08S8a z1;9xHE(174z&L<21VjOxCE$yMIAZ9V^?5?a#NW({Cnm*{ln=^uK#|ph3H&&3f|FZT zuP#>Y8r*u`SHSf;@cksl4FEj^`~|=P0^SF3kbu7e=q2E90Qv}kcggD`;DdyF{DO8p zg~#6pj`;9IMxG!t$A`6f9|0MItV7m7b0CgchyP=j^`96`2NuU3WL?f)n0z#)%|l`N zFudAuoNKF-%Ddx|Z@aHfNyYi?baPU2k4Sw~B#&xYHPbLvsx6;x)G+7ZNlW^RwHzN- zhIG@*QfB`R_rxfy?4!~lmTM_wEQzmX)^LGoGSHcX$Prtly(4D-2U=<&DSVnY&@TI@ zu`+j1Y7GY3f{FIYh>b-@OAEs8HA#aq=cON@cQzXoF3D>Krc(SPOeS1h1&0?x)@aV_e*u;YOA}B z-!E@K9uuA`ci5cG{-6-6>srU4$`$dh+UqR@;Ce>|s+-1}9FI9&TYG8b+8W%&2Y1`k zcTf6SLmXHfcdV#zZ55V}b(IRKv0b{c-DC~d*2(0qgVcA$0 z^6wX(AYv6QG-goS0R>j-PBt|Y9ldIMos zt6$y(Eknb95552LJuTMx?qOko8DyRBrD)fkr!`$>6R;$?(EUn?tWMI{Aq95^+;2*6 z1>k=^?r}fUGK1)KTXt@Ff`TJ}p^fPK@HImFSLWr@K853#rgQ6951J delta 2705 zcmaJ@4R9036~5a$NtP^O=`6{TY)kS+ZVRXnZ5>a-kP6|Ll+cnYOq1!P?L>4ekxpYvX{*o%g8KF( zBxfem^L+b#@9o=tyKnb&KC|KKDkWg!C*x8FgQ%UmslTtJI?A7-6#vHO_HU}SU*mL6 zuIxijH_7QzN=fnnpB&M@bCv$%gCN-r-&HzRMzXbdW@N2*r)i?#ku$)v_>_J~X*p9!>)@#JHB>3?6*!k_o zfP^??R1(9GP)Qsk%jhSWk-hztbUJh-v>5Ix4fPy?yGW;a4*mIyjzSOf)wtCCSl-SH zj@b_#>+-h3FZpl^E7zApHTRQ}_OWD}P*a7Ee|ZODzs9kn_yJv6ket6+7|Iuko25&q z@@{KE+6uD&OXXm}J4>>Hn4gW!U$|vTf-QtQX36Yf!7i?jUj3-)PhKUl9ZIH${j~ub zf!hTm)*0>zCIdqmK1jvQez zXy=5h7-T33^Pty+eW1S?_Cq@mu7>vAa1Dcst>Ic|*M;Xo`;+iI1{rn8Slp{QZ8l9W zIvBe(?Z@RtgFS9$(~@kdAs3f39*AnA5N5&_V=2B_Y|@uB7d&oUU#!)0rkv-1$&TMK z+0FfuI@WeJ?_XMMYt0$G8kov@C(C>_()4~|&TJO*PYWKuzH}r%(-$+u^ZuoJn>fp` z?<*Kq`)fI)mkJ^^p}iKbH_eA_<(AClmTYgl6G>KCim#X+LG}%}Va~QiMeb2a{4{Rq zC{+@JaZBz3#PuDw0(uHw{=#|ZB|blAZ?WyH@X15U&8Mj2wRq6%#GNHaknJpH%_6eJ z@iXR+2?-XNIB!}m5}M%l5$CGXPYB&>eHNT!Z(FrA>3r7~BHnM=Wn`_#f3=?iYpkzq z0gW8T@EZ;XvOkI6cg#ihT?d@oEzSip=a5UCvehNq$~nhnyxS=R%U+4<2H}u6BF>u( z0m+avdZ|Hafc&`A!VKKYw2(Us|aeSCksWp2(P=p0*1Z?TuJ8mEeJOe zmq2)kcpHS5h|3_Vi1-}{o`~Or@DXt(HHIp5w7YC9TE@%LHaXNPr`o2{52v@Jx5|*z zc^J9+aBZcx)Onb5^+D9A6xk4Ii9EnLKf_xp8=TJRxRjZEup~_?jCLM}5N zseGc6KYmM~>(bk%mZe(<+dj^8Gl<`Dz8Zf&y!xAd6P&eL<#NEOQ)jTRRseD3MN!WcuXeR72 z39AUhysLBmH931N8QvmnP~EqM7L`{Bn~3}S!h^Y}hX{KZVYA9bwZfKc2l7~Y$zB2- zYWoOjpH}5}NQ;f$xh2l&D2g)Kk0A0a!cE?Vi0{Ea@NPrSY5bm-CzboJx1LyEshVf@ zEP6BEbMT3{aBv6I5C%M2<>Nec0m(b7P!RikRlC(W9gvoCq-{{!A3}?Z`I-vXyh2iW zqcm%zYaU+5-%XN*_@(UqflYpVfvmaD4m8z%PF9}Swe_HVC~D2HcLggw`Qly<-5 Date: Fri, 18 Aug 2023 09:51:06 -0500 Subject: [PATCH 15/50] jtag/drivers/bcm2835gpio: do not configure push-pull inputs as output Previously, if a pin was configured as ADAPTER_GPIO_INIT_STATE_INPUT and its drive value was ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL, initialize_gpio would configure the pin as an output. The set_gpio_value function is optimized to not set the direction for pins configured as ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL as it only needs to be set once. When initialize_gpio performs this setup, it checked only that the drive value was ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL to set the output direction but did not exclude input pins which have already had their direction set. Now, input pins are ignored when initialize_gpio checks for ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL to set the mode to output. Change-Id: I4fc7a8132a6b00c7f213ec9fd05c7bbb37ee5f20 Fixes: 0dd969d83bad ("drivers/bcm2835gpio: Migrate to adapter gpio commands") Signed-off-by: Brandon Pupp [vfazio: update commit message] Signed-off-by: Vincent Fazio Reviewed-on: https://review.openocd.org/c/openocd/+/7862 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/drivers/bcm2835gpio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index 39e4af3657..f41f7b51ea 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -167,7 +167,8 @@ static void initialize_gpio(enum adapter_gpio_config_index idx) } /* Direction for non push-pull is already set by set_gpio_value() */ - if (adapter_gpio_config[idx].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL) + if (adapter_gpio_config[idx].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL + && adapter_gpio_config[idx].init_state != ADAPTER_GPIO_INIT_STATE_INPUT) OUT_GPIO(adapter_gpio_config[idx].gpio_num); bcm2835_gpio_synchronize(); } From 18281b0c497694d91c5608be54583172838be75c Mon Sep 17 00:00:00 2001 From: Robert Kovacsics Date: Sat, 19 Aug 2023 15:36:27 +0100 Subject: [PATCH 16/50] tcl/arc: Fix ARC v2 registers r22/r23 There was a typo in the register numbering. Signed-off-by: Robert Kovacsics Change-Id: Ie5d306725962c42f1bce976b80968145e6d0a177 Reviewed-on: https://review.openocd.org/c/openocd/+/7860 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- tcl/cpu/arc/v2.tcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tcl/cpu/arc/v2.tcl b/tcl/cpu/arc/v2.tcl index d28b9d9744..b24a67d0bd 100644 --- a/tcl/cpu/arc/v2.tcl +++ b/tcl/cpu/arc/v2.tcl @@ -173,8 +173,8 @@ proc arc_v2_init_regs { } { r19 19 uint32 r20 20 uint32 r21 21 uint32 - r22 23 uint32 - r23 24 uint32 + r22 22 uint32 + r23 23 uint32 r24 24 uint32 r25 25 uint32 gp 26 data_ptr From 022e438292de992cc558f268b2679e76ad313db6 Mon Sep 17 00:00:00 2001 From: Kirill Radkin Date: Tue, 8 Aug 2023 13:17:29 +0300 Subject: [PATCH 17/50] target: Change policy of removing watchpoints/breakpoints. Now internal watch/breakpoint will not be removed in case of error during removing triggers from hardware. Also change signature of some functions (for deletion bp/wp) to print message in case of some error. Change-Id: I71cd1f556a33975005d0ee372fc384fddfddc3bf Signed-off-by: Kirill Radkin Reviewed-on: https://review.openocd.org/c/openocd/+/7738 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/breakpoints.c | 163 +++++++++++++++++++++++++++++---------- src/target/breakpoints.h | 13 ++-- src/target/target.c | 23 ++++-- 3 files changed, 149 insertions(+), 50 deletions(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 4d268cebb3..5ce0346bb4 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -270,7 +270,7 @@ int hybrid_breakpoint_add(struct target *target, } /* free up a breakpoint */ -static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove) +static int breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove) { struct breakpoint *breakpoint = target->breakpoints; struct breakpoint **breakpoint_p = &target->breakpoints; @@ -284,14 +284,21 @@ static void breakpoint_free(struct target *target, struct breakpoint *breakpoint } if (!breakpoint) - return; + return ERROR_OK; retval = target_remove_breakpoint(target, breakpoint); + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "could not remove breakpoint #%d on this target", + breakpoint->number); + return retval; + } LOG_DEBUG("free BPID: %" PRIu32 " --> %d", breakpoint->unique_id, retval); (*breakpoint_p) = breakpoint->next; free(breakpoint->orig_instr); free(breakpoint); + + return ERROR_OK; } static int breakpoint_remove_internal(struct target *target, target_addr_t address) @@ -306,77 +313,121 @@ static int breakpoint_remove_internal(struct target *target, target_addr_t addre } if (breakpoint) { - breakpoint_free(target, breakpoint); - return 1; + return breakpoint_free(target, breakpoint); } else { - if (!target->smp) - LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address); - return 0; + return ERROR_BREAKPOINT_NOT_FOUND; } } -static void breakpoint_remove_all_internal(struct target *target) +static int breakpoint_remove_all_internal(struct target *target) { struct breakpoint *breakpoint = target->breakpoints; + int retval = ERROR_OK; while (breakpoint) { struct breakpoint *tmp = breakpoint; breakpoint = breakpoint->next; - breakpoint_free(target, tmp); + int status = breakpoint_free(target, tmp); + if (status != ERROR_OK) + retval = status; } + + return retval; } -void breakpoint_remove(struct target *target, target_addr_t address) +int breakpoint_remove(struct target *target, target_addr_t address) { + int retval = ERROR_OK; + unsigned int num_found_breakpoints = 0; if (target->smp) { - unsigned int num_breakpoints = 0; struct target_list *head; foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; - num_breakpoints += breakpoint_remove_internal(curr, address); + int status = breakpoint_remove_internal(curr, address); + + if (status != ERROR_BREAKPOINT_NOT_FOUND) { + num_found_breakpoints++; + + if (status != ERROR_OK) { + LOG_TARGET_ERROR(curr, "failed to remove breakpoint at address " TARGET_ADDR_FMT, address); + retval = status; + } + } } - if (!num_breakpoints) - LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address); + } else { - breakpoint_remove_internal(target, address); + retval = breakpoint_remove_internal(target, address); + + if (retval != ERROR_BREAKPOINT_NOT_FOUND) { + num_found_breakpoints++; + + if (retval != ERROR_OK) + LOG_TARGET_ERROR(target, "failed to remove breakpoint at address " TARGET_ADDR_FMT, address); + } } + + if (num_found_breakpoints == 0) + LOG_TARGET_ERROR(target, "no breakpoint at address " TARGET_ADDR_FMT " found", address); + + return retval; } -void breakpoint_remove_all(struct target *target) +int breakpoint_remove_all(struct target *target) { + int retval = ERROR_OK; if (target->smp) { struct target_list *head; foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; - breakpoint_remove_all_internal(curr); + int status = breakpoint_remove_all_internal(curr); + + if (status != ERROR_OK) + retval = status; } } else { - breakpoint_remove_all_internal(target); + retval = breakpoint_remove_all_internal(target); } + + return retval; } -static void breakpoint_clear_target_internal(struct target *target) +static int breakpoint_clear_target_internal(struct target *target) { LOG_DEBUG("Delete all breakpoints for target: %s", target_name(target)); - while (target->breakpoints) - breakpoint_free(target, target->breakpoints); + + int retval = ERROR_OK; + + while (target->breakpoints) { + int status = breakpoint_free(target, target->breakpoints); + if (status != ERROR_OK) + retval = status; + } + + return retval; } -void breakpoint_clear_target(struct target *target) +int breakpoint_clear_target(struct target *target) { + int retval = ERROR_OK; + if (target->smp) { struct target_list *head; foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; - breakpoint_clear_target_internal(curr); + int status = breakpoint_clear_target_internal(curr); + + if (status != ERROR_OK) + retval = status; } } else { - breakpoint_clear_target_internal(target); + retval = breakpoint_clear_target_internal(target); } + + return retval; } struct breakpoint *breakpoint_find(struct target *target, target_addr_t address) @@ -479,7 +530,7 @@ int watchpoint_add(struct target *target, target_addr_t address, } } -static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove) +static int watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove) { struct watchpoint *watchpoint = target->watchpoints; struct watchpoint **watchpoint_p = &target->watchpoints; @@ -493,11 +544,19 @@ static void watchpoint_free(struct target *target, struct watchpoint *watchpoint } if (!watchpoint) - return; + return ERROR_OK; retval = target_remove_watchpoint(target, watchpoint); + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "could not remove watchpoint #%d on this target", + watchpoint->number); + return retval; + } + LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval); (*watchpoint_p) = watchpoint->next; free(watchpoint); + + return ERROR_OK; } static int watchpoint_remove_internal(struct target *target, target_addr_t address) @@ -511,38 +570,62 @@ static int watchpoint_remove_internal(struct target *target, target_addr_t addre } if (watchpoint) { - watchpoint_free(target, watchpoint); - return 1; + return watchpoint_free(target, watchpoint); } else { - if (!target->smp) - LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address); - return 0; + return ERROR_WATCHPOINT_NOT_FOUND; } } -void watchpoint_remove(struct target *target, target_addr_t address) +int watchpoint_remove(struct target *target, target_addr_t address) { + int retval = ERROR_OK; + unsigned int num_found_watchpoints = 0; if (target->smp) { - unsigned int num_watchpoints = 0; struct target_list *head; foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; - num_watchpoints += watchpoint_remove_internal(curr, address); + int status = watchpoint_remove_internal(curr, address); + + if (status != ERROR_WATCHPOINT_NOT_FOUND) { + num_found_watchpoints++; + + if (status != ERROR_OK) { + LOG_TARGET_ERROR(curr, "failed to remove watchpoint at address" TARGET_ADDR_FMT, address); + retval = status; + } + } } - if (num_watchpoints == 0) - LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " num_watchpoints", address); } else { - watchpoint_remove_internal(target, address); + retval = watchpoint_remove_internal(target, address); + + if (retval != ERROR_WATCHPOINT_NOT_FOUND) { + num_found_watchpoints++; + + if (retval != ERROR_OK) + LOG_TARGET_ERROR(target, "failed to remove watchpoint at address" TARGET_ADDR_FMT, address); + } } + + if (num_found_watchpoints == 0) + LOG_TARGET_ERROR(target, "no watchpoint at address " TARGET_ADDR_FMT " found", address); + + return retval; } -void watchpoint_clear_target(struct target *target) +int watchpoint_clear_target(struct target *target) { + int retval = ERROR_OK; + LOG_DEBUG("Delete all watchpoints for target: %s", target_name(target)); - while (target->watchpoints) - watchpoint_free(target, target->watchpoints); + while (target->watchpoints) { + int status = watchpoint_free(target, target->watchpoints); + if (status != ERROR_OK) + retval = status; + } + + return retval; } int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h index d447515bff..daa31f711c 100644 --- a/src/target/breakpoints.h +++ b/src/target/breakpoints.h @@ -50,15 +50,15 @@ struct watchpoint { int unique_id; }; -void breakpoint_clear_target(struct target *target); +int breakpoint_clear_target(struct target *target); int breakpoint_add(struct target *target, target_addr_t address, uint32_t length, enum breakpoint_type type); int context_breakpoint_add(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type); int hybrid_breakpoint_add(struct target *target, target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type); -void breakpoint_remove(struct target *target, target_addr_t address); -void breakpoint_remove_all(struct target *target); +int breakpoint_remove(struct target *target, target_addr_t address); +int breakpoint_remove_all(struct target *target); struct breakpoint *breakpoint_find(struct target *target, target_addr_t address); @@ -68,11 +68,11 @@ static inline void breakpoint_hw_set(struct breakpoint *breakpoint, unsigned int breakpoint->number = hw_number; } -void watchpoint_clear_target(struct target *target); +int watchpoint_clear_target(struct target *target); int watchpoint_add(struct target *target, target_addr_t address, uint32_t length, enum watchpoint_rw rw, uint64_t value, uint64_t mask); -void watchpoint_remove(struct target *target, target_addr_t address); +int watchpoint_remove(struct target *target, target_addr_t address); /* report type and address of just hit watchpoint */ int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, @@ -84,4 +84,7 @@ static inline void watchpoint_set(struct watchpoint *watchpoint, unsigned int nu watchpoint->number = number; } +#define ERROR_BREAKPOINT_NOT_FOUND (-1600) +#define ERROR_WATCHPOINT_NOT_FOUND (-1601) + #endif /* OPENOCD_TARGET_BREAKPOINTS_H */ diff --git a/src/target/target.c b/src/target/target.c index 96f4ae7d3e..5c4f67b6a7 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4034,21 +4034,31 @@ COMMAND_HANDLER(handle_bp_command) COMMAND_HANDLER(handle_rbp_command) { + int retval; + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; struct target *target = get_current_target(CMD_CTX); if (!strcmp(CMD_ARGV[0], "all")) { - breakpoint_remove_all(target); + retval = breakpoint_remove_all(target); + + if (retval != ERROR_OK) { + command_print(CMD, "Error encountered during removal of all breakpoints."); + command_print(CMD, "Some breakpoints may have remained set."); + } } else { target_addr_t addr; COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); - breakpoint_remove(target, addr); + retval = breakpoint_remove(target, addr); + + if (retval != ERROR_OK) + command_print(CMD, "Error during removal of breakpoint at address " TARGET_ADDR_FMT, addr); } - return ERROR_OK; + return retval; } COMMAND_HANDLER(handle_wp_command) @@ -4133,9 +4143,12 @@ COMMAND_HANDLER(handle_rwp_command) COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); struct target *target = get_current_target(CMD_CTX); - watchpoint_remove(target, addr); + int retval = watchpoint_remove(target, addr); - return ERROR_OK; + if (retval != ERROR_OK) + command_print(CMD, "Error during removal of watchpoint at address " TARGET_ADDR_FMT, addr); + + return retval; } /** From 6f986d2cd78e1502e840d7c5f06e67ed8bbc352b Mon Sep 17 00:00:00 2001 From: Marek Vrbka Date: Wed, 23 Aug 2023 15:20:47 +0200 Subject: [PATCH 18/50] target: Unify the output of "bp" command This patch unifies the lines printed by the "bp" command so that different types of breakpoints are printed in the same format. Change-Id: Ic1335eda1c58072a334aed9cf0011431c8ec86a4 Signed-off-by: Marek Vrbka Reviewed-on: https://review.openocd.org/c/openocd/+/7861 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/target.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 5c4f67b6a7..1219743750 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3926,24 +3926,24 @@ static int handle_bp_command_list(struct command_invocation *cmd) if (breakpoint->type == BKPT_SOFT) { char *buf = buf_to_hex_str(breakpoint->orig_instr, breakpoint->length); - command_print(cmd, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, 0x%s", + command_print(cmd, "Software breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, orig_instr=0x%s", breakpoint->address, breakpoint->length, buf); free(buf); } else { if ((breakpoint->address == 0) && (breakpoint->asid != 0)) - command_print(cmd, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %u", + command_print(cmd, "Context breakpoint: asid=0x%8.8" PRIx32 ", len=0x%x, num=%u", breakpoint->asid, breakpoint->length, breakpoint->number); else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { - command_print(cmd, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %u", + command_print(cmd, "Hybrid breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, num=%u", breakpoint->address, breakpoint->length, breakpoint->number); command_print(cmd, "\t|--->linked with ContextID: 0x%8.8" PRIx32, breakpoint->asid); } else - command_print(cmd, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %u", + command_print(cmd, "Hardware breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, num=%u", breakpoint->address, breakpoint->length, breakpoint->number); } From 2839a873a3e93c8f744352fc1671c2db6297937b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 28 Aug 2023 12:11:48 +0200 Subject: [PATCH 19/50] doc/style: clarify default case for enumerators Enumerator's case were not specified in the coding style. Add enumerators together with macros for upper-case preference. While there, add the word CamelCase beside the less common, but already used, MixedCaps. This could help linking this chapter to the output of checkpatch script. Change-Id: I6d4af06cc6f4bc46f525e99e9a74ecc167606c49 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/7875 Reviewed-by: Tomas Vanek Tested-by: jenkins --- doc/manual/style.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/style.txt b/doc/manual/style.txt index 58f39807e2..1d3ec6748d 100644 --- a/doc/manual/style.txt +++ b/doc/manual/style.txt @@ -111,8 +111,8 @@ Finally, try to avoid lines of code that are longer than 72-80 columns: @section stylenames Naming Rules - most identifiers must use lower-case letters (and digits) only. - - macros must use upper-case letters (and digits) only. - - OpenOCD identifiers should NEVER use @c MixedCaps. + - macros and enumerators must use upper-case letters (and digits) only. + - OpenOCD identifiers should NEVER use @c MixedCaps, aka @c CamelCase. - @c typedef names must end with the '_t' suffix. - This should be reserved for types that should be passed by value. - Do @b not mix the typedef keyword with @c struct. From 62f76b2169302b9500deea737a017168271824ac Mon Sep 17 00:00:00 2001 From: Luca Hung Date: Mon, 31 Jul 2023 15:08:18 +0800 Subject: [PATCH 20/50] flash/nor: add support for Nuvoton NPCX4/K3 series flash Added NPCX flash driver to support the Nuvoton NPCX4/K3 series microcontrollers. Add config file for these series. Change-Id: I0b6e128fa51146b561f422e23a98260594b1f138 Signed-off-by: Luca Hung Signed-off-by: Mulin CHao Reviewed-on: https://review.openocd.org/c/openocd/+/7794 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- contrib/loaders/flash/npcx/npcx_algo.inc | 126 ++++++------ contrib/loaders/flash/npcx/npcx_flash.c | 181 ++++++++++++------ contrib/loaders/flash/npcx/npcx_flash.h | 13 +- .../loaders/flash/npcx/npcx_flash_config.h | 2 +- doc/openocd.texi | 8 +- src/flash/nor/npcx.c | 48 +++-- tcl/target/npcx.cfg | 10 +- 7 files changed, 247 insertions(+), 141 deletions(-) diff --git a/contrib/loaders/flash/npcx/npcx_algo.inc b/contrib/loaders/flash/npcx/npcx_algo.inc index 4312fdb1b4..46b79d8d9c 100644 --- a/contrib/loaders/flash/npcx/npcx_algo.inc +++ b/contrib/loaders/flash/npcx/npcx_algo.inc @@ -1,60 +1,70 @@ /* Autogenerated with ../../../../src/helper/bin2char.sh */ -0x08,0xb5,0xdf,0xf8,0x08,0xd0,0x00,0xf0,0x2f,0xf9,0x00,0x00,0x48,0x15,0x0c,0x20, -0x03,0x4b,0x18,0x70,0x19,0x72,0x08,0x33,0x1a,0x78,0xd2,0x09,0xfc,0xd1,0x70,0x47, -0x16,0x00,0x02,0x40,0x70,0xb5,0x11,0x4c,0x23,0x78,0x03,0xf0,0xfd,0x03,0x23,0x70, -0xc0,0x21,0x05,0x20,0xff,0xf7,0xec,0xff,0x0d,0x4a,0x0e,0x49,0x6f,0xf0,0x7f,0x43, -0x6f,0xf0,0x2e,0x05,0x10,0x46,0x15,0x70,0x06,0x78,0xf6,0x09,0xfc,0xd1,0x0e,0x78, -0xf6,0x07,0x01,0xd5,0x01,0x3b,0xf6,0xd1,0x22,0x78,0x42,0xf0,0x02,0x02,0x00,0x2b, -0x22,0x70,0x0c,0xbf,0x03,0x20,0x00,0x20,0x70,0xbd,0x00,0xbf,0x1f,0x00,0x02,0x40, +0x08,0xb5,0xdf,0xf8,0x08,0xd0,0x00,0xf0,0x95,0xf9,0x00,0x00,0xec,0x15,0x0c,0x20, +0x03,0x4b,0x18,0x70,0x08,0x33,0x19,0x70,0x1a,0x78,0xd2,0x09,0xfc,0xd1,0x70,0x47, +0x16,0x00,0x02,0x40,0x13,0x4b,0x14,0x49,0x1a,0x68,0xea,0xb1,0x1a,0x68,0x01,0x2a, +0x1e,0xd0,0x1b,0x68,0x02,0x2b,0x1b,0xd1,0x10,0x4b,0x1a,0x78,0x50,0xb1,0x02,0xf0, +0xf7,0x02,0x1a,0x70,0x01,0x22,0x08,0x78,0x01,0x23,0x93,0x40,0x03,0x43,0xdb,0xb2, +0x0b,0x70,0x70,0x47,0x42,0xf0,0x08,0x02,0x1a,0x70,0x01,0x22,0x08,0x78,0x01,0x23, +0x93,0x40,0x20,0xea,0x03,0x03,0xf3,0xe7,0x01,0x22,0x00,0x28,0xf6,0xd0,0xea,0xe7, +0x00,0x22,0xfa,0xe7,0x00,0x00,0x0c,0x20,0x1f,0x00,0x02,0x40,0x43,0x00,0x02,0x40, +0x73,0xb5,0x04,0x46,0x00,0x20,0x15,0x46,0x0e,0x46,0xff,0xf7,0xcb,0xff,0x0f,0x4b, +0x01,0x94,0xc4,0xf3,0x07,0x44,0x1c,0x70,0x9d,0xf8,0x05,0x20,0x5a,0x70,0x9d,0xf8, +0x04,0x20,0x9a,0x70,0xf3,0x21,0x02,0x20,0xff,0xf7,0xb2,0xff,0x2c,0x46,0x63,0x1b, +0xb3,0x42,0x05,0xd3,0x01,0x20,0x02,0xb0,0xbd,0xe8,0x70,0x40,0xff,0xf7,0xb2,0xbf, +0xe0,0x21,0x14,0xf8,0x01,0x0b,0xff,0xf7,0xa3,0xff,0xf0,0xe7,0x1a,0x00,0x02,0x40, +0x08,0x4b,0x1b,0x68,0x02,0x2b,0x08,0x4b,0x07,0xd1,0x08,0x4a,0x80,0x21,0x11,0x70, +0xc0,0x22,0x1a,0x70,0x00,0x22,0x1a,0x71,0x70,0x47,0x1a,0x78,0x42,0xf0,0x80,0x02, +0x1a,0x70,0x70,0x47,0x00,0x00,0x0c,0x20,0x10,0x30,0x0c,0x40,0x00,0x30,0x0c,0x40, +0x38,0xb5,0x00,0x20,0xff,0xf7,0x8e,0xff,0xc0,0x21,0x05,0x20,0xff,0xf7,0x80,0xff, +0x0b,0x4b,0x0c,0x4a,0x6f,0xf0,0x7f,0x44,0x6f,0xf0,0x2e,0x00,0x19,0x46,0x18,0x70, +0x0d,0x78,0xed,0x09,0xfc,0xd1,0x15,0x78,0xed,0x07,0x01,0xd5,0x01,0x3c,0xf6,0xd1, +0x01,0x20,0xff,0xf7,0x77,0xff,0x00,0x2c,0x0c,0xbf,0x03,0x20,0x00,0x20,0x38,0xbd, 0x1e,0x00,0x02,0x40,0x1a,0x00,0x02,0x40,0x08,0xb5,0xc0,0x21,0x06,0x20,0xff,0xf7, -0xc7,0xff,0xff,0xf7,0xcf,0xff,0x28,0xb9,0x03,0x4b,0x1b,0x78,0x13,0xf0,0x02,0x0f, -0x08,0xbf,0x02,0x20,0x08,0xbd,0x00,0xbf,0x1a,0x00,0x02,0x40,0xf8,0xb5,0x12,0x4c, -0x23,0x78,0x03,0xf0,0xfd,0x03,0x23,0x70,0x10,0x4b,0x17,0x46,0xc0,0xf3,0x07,0x42, -0x1a,0x70,0xc0,0xf3,0x07,0x22,0xc0,0xb2,0x03,0xf8,0x01,0x2c,0x0e,0x46,0x03,0xf8, -0x02,0x0c,0xe8,0x21,0x02,0x20,0xff,0xf7,0xa3,0xff,0x00,0x25,0xae,0x42,0x04,0xd8, -0x23,0x78,0x43,0xf0,0x02,0x03,0x23,0x70,0xf8,0xbd,0x78,0x5d,0xe0,0x21,0xff,0xf7, -0x97,0xff,0x01,0x35,0xf2,0xe7,0x00,0xbf,0x1f,0x00,0x02,0x40,0x19,0x00,0x02,0x40, -0x70,0x47,0x2d,0xe9,0xf0,0x41,0x00,0xf1,0xff,0x06,0x26,0xf0,0xff,0x06,0x34,0x1a, -0x8c,0x42,0x28,0xbf,0x0c,0x46,0x80,0x46,0x0d,0x46,0x17,0x46,0x5c,0xb1,0xff,0xf7, -0xb3,0xff,0x58,0xb9,0x3a,0x46,0xa1,0xb2,0x40,0x46,0xff,0xf7,0xbf,0xff,0xff,0xf7, -0x81,0xff,0x18,0xb9,0x27,0x44,0x2c,0x1b,0x14,0xb9,0x20,0x46,0xbd,0xe8,0xf0,0x81, -0xb4,0xf5,0x80,0x7f,0x25,0x46,0x28,0xbf,0x4f,0xf4,0x80,0x75,0xff,0xf7,0x9c,0xff, -0x00,0x28,0xf3,0xd1,0x3a,0x46,0xa9,0xb2,0x30,0x46,0xff,0xf7,0xa7,0xff,0xff,0xf7, -0x69,0xff,0x00,0x28,0xea,0xd1,0x2f,0x44,0x2e,0x44,0x64,0x1b,0xe4,0xe7,0x00,0x00, -0x2d,0xe9,0xf0,0x47,0x14,0x4e,0x15,0x4f,0xdf,0xf8,0x54,0x80,0x05,0x46,0x0c,0x46, -0x8a,0x46,0x05,0xeb,0x04,0x09,0xa9,0xeb,0x0a,0x09,0xba,0xf1,0x00,0x0f,0x02,0xd1, -0x50,0x46,0xbd,0xe8,0xf0,0x87,0xff,0xf7,0x77,0xff,0x00,0x28,0xf9,0xd1,0xc9,0xf3, -0x07,0x43,0x33,0x70,0xc9,0xf3,0x07,0x23,0x5f,0xfa,0x89,0xf9,0x3b,0x70,0xc8,0x21, -0x20,0x20,0x88,0xf8,0x00,0x90,0xff,0xf7,0x33,0xff,0xff,0xf7,0x3b,0xff,0x00,0x28, -0xe7,0xd1,0xaa,0xf5,0x80,0x5a,0xdc,0xe7,0x19,0x00,0x02,0x40,0x18,0x00,0x02,0x40, -0x17,0x00,0x02,0x40,0x08,0xb5,0xff,0xf7,0x57,0xff,0x38,0xb9,0xc0,0x21,0xc7,0x20, -0xff,0xf7,0x1e,0xff,0xbd,0xe8,0x08,0x40,0xff,0xf7,0x24,0xbf,0x08,0xbd,0x00,0x00, -0x38,0xb5,0xff,0xf7,0x49,0xff,0x04,0x46,0xc0,0xb9,0x0d,0x4b,0x0d,0x4d,0xf2,0x21, -0x28,0x70,0x18,0x70,0x01,0x20,0xff,0xf7,0x0b,0xff,0xff,0xf7,0x13,0xff,0x04,0x46, -0x60,0xb9,0xc1,0x21,0x05,0x20,0xff,0xf7,0x03,0xff,0x2b,0x78,0x2b,0xb9,0xc1,0x21, -0x35,0x20,0xff,0xf7,0xfd,0xfe,0x2b,0x78,0x03,0xb1,0x02,0x24,0x20,0x46,0x38,0xbd, -0x1b,0x00,0x02,0x40,0x1a,0x00,0x02,0x40,0x10,0xb5,0xc3,0x21,0x04,0x46,0x9f,0x20, -0xff,0xf7,0xee,0xfe,0x06,0x4b,0x07,0x4a,0x19,0x78,0x01,0x33,0x00,0x20,0x1b,0x78, -0x12,0x78,0x1b,0x02,0x43,0xea,0x01,0x43,0x13,0x43,0x23,0x60,0x10,0xbd,0x00,0xbf, -0x1a,0x00,0x02,0x40,0x1c,0x00,0x02,0x40,0x08,0xb5,0x10,0x22,0x00,0x21,0x00,0xf0, -0x4d,0xf8,0x00,0x20,0x08,0xbd,0x00,0x00,0x73,0xb5,0x21,0x48,0x20,0x4c,0xff,0xf7, -0xf3,0xff,0x20,0x4a,0x13,0x78,0x43,0xf0,0x80,0x03,0x13,0x70,0xff,0xf7,0xb0,0xff, -0x05,0x46,0x58,0xb9,0x1c,0x4e,0xe3,0x68,0x00,0x2b,0xfc,0xd0,0xa3,0x68,0x01,0x3b, -0x03,0x2b,0x2a,0xd8,0xdf,0xe8,0x03,0xf0,0x04,0x18,0x20,0x23,0xe5,0x60,0xfd,0xe7, -0x01,0xa8,0xff,0xf7,0xc1,0xff,0xa8,0xb9,0x01,0x9b,0x33,0x70,0x1a,0x0a,0x1b,0x0c, -0x72,0x70,0xb3,0x70,0xf0,0x70,0x23,0x7b,0x25,0x73,0x63,0x7b,0x65,0x73,0xa3,0x7b, -0xa5,0x73,0xe3,0x7b,0xe5,0x73,0xde,0xe7,0x20,0x68,0x61,0x68,0xff,0xf7,0x48,0xff, -0x00,0x28,0xf0,0xd0,0xe0,0x60,0xfe,0xe7,0xff,0xf7,0x74,0xff,0xf8,0xe7,0x20,0x68, -0x61,0x68,0x32,0x46,0xff,0xf7,0x05,0xff,0xf2,0xe7,0x01,0x20,0xf2,0xe7,0x00,0xbf, -0x00,0x00,0x0c,0x20,0x10,0x30,0x0c,0x40,0x10,0x00,0x0c,0x20,0xf0,0xb5,0x05,0x00, -0x83,0x07,0x4e,0xd0,0x54,0x1e,0x00,0x2a,0x46,0xd0,0x0a,0x06,0x12,0x0e,0x03,0x00, -0x03,0x26,0x02,0xe0,0x01,0x35,0x01,0x3c,0x3e,0xd3,0x01,0x33,0x2a,0x70,0x33,0x42, -0xf8,0xd1,0x03,0x2c,0x2f,0xd9,0xff,0x22,0x0a,0x40,0x15,0x02,0x15,0x43,0x2a,0x04, -0x15,0x43,0x0f,0x2c,0x38,0xd9,0x27,0x00,0x10,0x3f,0x3f,0x09,0x3e,0x01,0xb4,0x46, -0x1e,0x00,0x1a,0x00,0x10,0x36,0x66,0x44,0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60, -0x10,0x32,0xb2,0x42,0xf8,0xd1,0x0f,0x26,0x0c,0x22,0x01,0x37,0x3f,0x01,0x26,0x40, -0xdb,0x19,0x37,0x00,0x22,0x42,0x1a,0xd0,0x3e,0x1f,0xb6,0x08,0xb4,0x00,0xa4,0x46, -0x1a,0x00,0x1c,0x1d,0x64,0x44,0x20,0xc2,0xa2,0x42,0xfc,0xd1,0x03,0x24,0x01,0x36, -0xb6,0x00,0x9b,0x19,0x3c,0x40,0x00,0x2c,0x06,0xd0,0x09,0x06,0x1c,0x19,0x09,0x0e, -0x19,0x70,0x01,0x33,0x9c,0x42,0xfb,0xd1,0xf0,0xbc,0x02,0xbc,0x08,0x47,0x34,0x00, -0xf1,0xe7,0x14,0x00,0x03,0x00,0xbc,0xe7,0x27,0x00,0xdd,0xe7, +0x5f,0xff,0xff,0xf7,0xd5,0xff,0x28,0xb9,0x03,0x4b,0x1b,0x78,0x13,0xf0,0x02,0x0f, +0x08,0xbf,0x02,0x20,0x08,0xbd,0x00,0xbf,0x1a,0x00,0x02,0x40,0x70,0x47,0x00,0x00, +0x38,0xb5,0x17,0x4c,0xc1,0x21,0x05,0x20,0xff,0xf7,0x4a,0xff,0x25,0x78,0xc1,0x21, +0x35,0x20,0xff,0xf7,0x45,0xff,0x23,0x78,0xed,0xb2,0xdb,0xb2,0x05,0xb9,0xd3,0xb1, +0xff,0xf7,0xda,0xff,0xd0,0xb9,0x0f,0x4b,0x20,0x70,0xf2,0x21,0x18,0x70,0x01,0x20, +0xff,0xf7,0x36,0xff,0xff,0xf7,0xac,0xff,0x80,0xb9,0xc1,0x21,0x05,0x20,0xff,0xf7, +0x2f,0xff,0x25,0x78,0xc1,0x21,0x35,0x20,0xff,0xf7,0x2a,0xff,0x23,0x78,0xed,0xb2, +0xdb,0xb2,0x15,0xb9,0x0b,0xb9,0x00,0x20,0x38,0xbd,0x02,0x20,0x38,0xbd,0x00,0xbf, +0x1a,0x00,0x02,0x40,0x1b,0x00,0x02,0x40,0x2d,0xe9,0xf8,0x43,0x81,0x46,0x0d,0x46, +0x90,0x46,0xff,0xf7,0x75,0xff,0xff,0xf7,0xc3,0xff,0x06,0x46,0xb8,0xb9,0x09,0xf1, +0xff,0x07,0x27,0xf0,0xff,0x07,0xa7,0xeb,0x09,0x04,0xac,0x42,0x28,0xbf,0x2c,0x46, +0x5c,0xb1,0xff,0xf7,0xa1,0xff,0x10,0xbb,0x42,0x46,0xa1,0xb2,0x48,0x46,0xff,0xf7, +0x37,0xff,0xff,0xf7,0x75,0xff,0xd0,0xb9,0xa0,0x44,0x2c,0x1b,0x14,0xb9,0x30,0x46, +0xbd,0xe8,0xf8,0x83,0xff,0xf7,0x90,0xff,0x88,0xb9,0xb4,0xf5,0x80,0x7f,0x25,0x46, +0x28,0xbf,0x4f,0xf4,0x80,0x75,0x42,0x46,0xa9,0xb2,0x38,0x46,0xff,0xf7,0x20,0xff, +0xff,0xf7,0x5e,0xff,0x18,0xb9,0xa8,0x44,0x2f,0x44,0x64,0x1b,0xe6,0xe7,0x06,0x46, +0xe5,0xe7,0x00,0x00,0x2d,0xe9,0xf7,0x4f,0x06,0x46,0x0d,0x46,0xff,0xf7,0x38,0xff, +0xff,0xf7,0x86,0xff,0x82,0x46,0x58,0xb9,0x15,0x4f,0xdf,0xf8,0x58,0x80,0xdf,0xf8, +0x58,0x90,0xab,0x46,0x74,0x19,0xa4,0xeb,0x0b,0x04,0xbb,0xf1,0x00,0x0f,0x03,0xd1, +0x50,0x46,0x03,0xb0,0xbd,0xe8,0xf0,0x8f,0xff,0xf7,0x5e,0xff,0xa8,0xb9,0x01,0x94, +0xc4,0xf3,0x07,0x44,0x3c,0x70,0x9d,0xf8,0x05,0x30,0x88,0xf8,0x00,0x30,0x9d,0xf8, +0x04,0x30,0x89,0xf8,0x00,0x30,0xf3,0x21,0x20,0x20,0xff,0xf7,0xb1,0xfe,0xff,0xf7, +0x27,0xff,0x10,0xb9,0xab,0xf5,0x80,0x5b,0xdc,0xe7,0x82,0x46,0xe0,0xe7,0x00,0xbf, +0x1a,0x00,0x02,0x40,0x1b,0x00,0x02,0x40,0x1c,0x00,0x02,0x40,0x08,0xb5,0xff,0xf7, +0xff,0xfe,0xff,0xf7,0x4d,0xff,0x50,0xb9,0xff,0xf7,0x36,0xff,0x38,0xb9,0xc0,0x21, +0xc7,0x20,0xff,0xf7,0x95,0xfe,0xbd,0xe8,0x08,0x40,0xff,0xf7,0x09,0xbf,0x08,0xbd, +0x10,0xb5,0x04,0x46,0xff,0xf7,0xec,0xfe,0xc3,0x21,0x9f,0x20,0xff,0xf7,0x88,0xfe, +0x06,0x4b,0x07,0x4a,0x19,0x78,0x01,0x33,0x00,0x20,0x1b,0x78,0x12,0x78,0x1b,0x02, +0x43,0xea,0x01,0x43,0x13,0x43,0x23,0x60,0x10,0xbd,0x00,0xbf,0x1a,0x00,0x02,0x40, +0x1c,0x00,0x02,0x40,0x08,0xb5,0x14,0x22,0x00,0x21,0x00,0xf0,0x41,0xf8,0x00,0x20, +0x08,0xbd,0x00,0x00,0x73,0xb5,0x1c,0x48,0x1b,0x4e,0x1c,0x4d,0xff,0xf7,0xf2,0xff, +0x34,0x46,0x33,0x69,0x00,0x2b,0xfc,0xd0,0xf3,0x68,0x01,0x3b,0x03,0x2b,0x29,0xd8, +0xdf,0xe8,0x03,0xf0,0x02,0x17,0x1f,0x22,0x01,0xa8,0xff,0xf7,0xc9,0xff,0xb0,0xb9, +0x01,0x9b,0x2b,0x70,0x19,0x0a,0x1b,0x0c,0x69,0x70,0xab,0x70,0xe8,0x70,0x23,0x7c, +0x00,0x23,0x23,0x74,0x62,0x7c,0x63,0x74,0xa2,0x7c,0xa3,0x74,0xe2,0x7c,0xe3,0x74, +0xdf,0xe7,0x60,0x68,0xa1,0x68,0xff,0xf7,0x65,0xff,0x00,0x28,0xef,0xd0,0x20,0x61, +0xfe,0xe7,0xff,0xf7,0x9b,0xff,0xf8,0xe7,0x60,0x68,0xa1,0x68,0x2a,0x46,0xff,0xf7, +0x1b,0xff,0xf2,0xe7,0x01,0x20,0xf2,0xe7,0x00,0x00,0x0c,0x20,0x14,0x00,0x0c,0x20, +0xf0,0xb5,0x83,0x07,0x47,0xd0,0x54,0x1e,0x00,0x2a,0x41,0xd0,0x0d,0x06,0x2d,0x0e, +0x02,0x00,0x03,0x26,0x02,0xe0,0x1a,0x00,0x01,0x3c,0x39,0xd3,0x53,0x1c,0x15,0x70, +0x33,0x42,0xf8,0xd1,0x03,0x2c,0x2a,0xd9,0xff,0x22,0x0a,0x40,0x15,0x02,0x15,0x43, +0x2a,0x04,0x15,0x43,0x0f,0x2c,0x14,0xd9,0x27,0x00,0x1a,0x00,0x10,0x3f,0x3e,0x09, +0x01,0x36,0x36,0x01,0x9e,0x19,0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60,0x10,0x32, +0x96,0x42,0xf8,0xd1,0x0f,0x22,0x97,0x43,0x10,0x37,0xdb,0x19,0x14,0x40,0x03,0x2c, +0x0d,0xd9,0x1a,0x00,0x27,0x1f,0xbe,0x08,0x01,0x36,0xb6,0x00,0x9e,0x19,0x20,0xc2, +0xb2,0x42,0xfc,0xd1,0x03,0x22,0x97,0x43,0x04,0x37,0xdb,0x19,0x14,0x40,0x00,0x2c, +0x06,0xd0,0x09,0x06,0x1c,0x19,0x09,0x0e,0x19,0x70,0x01,0x33,0x9c,0x42,0xfb,0xd1, +0xf0,0xbc,0x02,0xbc,0x08,0x47,0x14,0x00,0x03,0x00,0xc3,0xe7, diff --git a/contrib/loaders/flash/npcx/npcx_flash.c b/contrib/loaders/flash/npcx/npcx_flash.c index 7d59123aab..6df01b2d43 100644 --- a/contrib/loaders/flash/npcx/npcx_flash.c +++ b/contrib/loaders/flash/npcx/npcx_flash.c @@ -10,9 +10,29 @@ #include #include "npcx_flash.h" +/* flashloader parameter structure */ +__attribute__ ((section(".buffers.g_cfg"))) +static volatile struct npcx_flash_params g_cfg; +/* data buffer */ +__attribute__ ((section(".buffers.g_buf"))) +static uint8_t g_buf[NPCX_FLASH_LOADER_BUFFER_SIZE]; + /*---------------------------------------------------------------------------- * NPCX flash driver *----------------------------------------------------------------------------*/ +static void flash_init(void) +{ + if (g_cfg.fiu_ver == NPCX_FIU_NPCK) { + /* Set pinmux to SHD flash */ + NPCX_DEVCNT = 0x80; + NPCX_DEVALT(0) = 0xC0; + NPCX_DEVALT(4) = 0x00; + } else { + /* Avoid F_CS0 toggles while programming the internal flash. */ + NPCX_SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI); + } +} + static void flash_execute_cmd(uint8_t code, uint8_t cts) { /* Set UMA code */ @@ -26,11 +46,26 @@ static void flash_execute_cmd(uint8_t code, uint8_t cts) static void flash_cs_level(uint8_t level) { + int sw_cs = 0; + + if (g_cfg.fiu_ver == NPCX_FIU_NPCX) { + sw_cs = 1; + } else if (g_cfg.fiu_ver == NPCX_FIU_NPCX_V2) { + sw_cs = 0; + } else if (g_cfg.fiu_ver == NPCX_FIU_NPCK) { + sw_cs = 1; + /* Unlock UMA before pulling down CS in NPCK series */ + if (level) + NPCX_CLEAR_BIT(NPCX_FIU_MSR_IE_CFG, NPCX_FIU_MSR_IE_CFG_UMA_BLOCK); + else + NPCX_SET_BIT(NPCX_FIU_MSR_IE_CFG, NPCX_FIU_MSR_IE_CFG_UMA_BLOCK); + } + /* Program chip select pin to high/low level */ if (level) - NPCX_SET_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1); + NPCX_SET_BIT(NPCX_UMA_ECTS, sw_cs); else - NPCX_CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1); + NPCX_CLEAR_BIT(NPCX_UMA_ECTS, sw_cs); } static void flash_set_address(uint32_t dest_addr) @@ -38,15 +73,15 @@ static void flash_set_address(uint32_t dest_addr) uint8_t *addr = (uint8_t *)&dest_addr; /* Set target flash address */ - NPCX_UMA_AB2 = addr[2]; - NPCX_UMA_AB1 = addr[1]; - NPCX_UMA_AB0 = addr[0]; + NPCX_UMA_DB0 = addr[2]; + NPCX_UMA_DB1 = addr[1]; + NPCX_UMA_DB2 = addr[0]; } -void delay(uint32_t i) +static void delay(uint32_t i) { while (i--) - ; + __asm__ volatile ("nop"); } static int flash_wait_ready(uint32_t timeout) @@ -104,7 +139,7 @@ static void flash_burst_write(uint32_t dest_addr, uint16_t bytes, /* Set write address */ flash_set_address(dest_addr); /* Start programming */ - flash_execute_cmd(NPCX_CMD_FLASH_PROGRAM, NPCX_MASK_CMD_WR_ADR); + flash_execute_cmd(NPCX_CMD_FLASH_PROGRAM, NPCX_MASK_CMD_WR_3BYTE); for (uint32_t i = 0; i < bytes; i++) { flash_execute_cmd(*data, NPCX_MASK_CMD_WR_ONLY); data++; @@ -114,6 +149,15 @@ static void flash_burst_write(uint32_t dest_addr, uint16_t bytes, flash_cs_level(1); } +static void flash_get_stsreg(uint8_t *reg1, uint8_t *reg2) +{ + /* Read status register 1/2 for checking */ + flash_execute_cmd(NPCX_CMD_READ_STATUS_REG, NPCX_MASK_CMD_RD_1BYTE); + *reg1 = NPCX_UMA_DB0; + flash_execute_cmd(NPCX_CMD_READ_STATUS_REG2, NPCX_MASK_CMD_RD_1BYTE); + *reg2 = NPCX_UMA_DB0; +} + /* The data to write cannot cross 256 Bytes boundary */ static int flash_program_write(uint32_t addr, uint32_t size, const uint8_t *data) @@ -126,7 +170,41 @@ static int flash_program_write(uint32_t addr, uint32_t size, return flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT); } -int flash_physical_write(uint32_t offset, uint32_t size, const uint8_t *data) +static int flash_physical_clear_stsreg(void) +{ + int status; + uint8_t reg1, reg2; + + /* Read status register 1/2 for checking */ + flash_get_stsreg(®1, ®2); + if (reg1 == 0x00 && reg2 == 0x00) + return NPCX_FLASH_STATUS_OK; + + /* Enable write */ + status = flash_write_enable(); + if (status != NPCX_FLASH_STATUS_OK) + return status; + + NPCX_UMA_DB0 = 0x0; + NPCX_UMA_DB1 = 0x0; + + /* Write status register 1/2 */ + flash_execute_cmd(NPCX_CMD_WRITE_STATUS_REG, NPCX_MASK_CMD_WR_2BYTE); + + /* Wait writing completed */ + status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT); + if (status != NPCX_FLASH_STATUS_OK) + return status; + + /* Read status register 1/2 for checking */ + flash_get_stsreg(®1, ®2); + if (reg1 != 0x00 || reg2 != 0x00) + return NPCX_FLASH_STATUS_FAILED; + + return NPCX_FLASH_STATUS_OK; +} + +static int flash_physical_write(uint32_t offset, uint32_t size, const uint8_t *data) { int status; uint32_t trunk_start = (offset + 0xff) & ~0xff; @@ -135,6 +213,13 @@ int flash_physical_write(uint32_t offset, uint32_t size, const uint8_t *data) uint32_t dest_addr = offset; uint32_t write_len = ((trunk_start - offset) > size) ? size : (trunk_start - offset); + /* Configure fiu and clear status registers if needed */ + flash_init(); + status = flash_physical_clear_stsreg(); + if (status != NPCX_FLASH_STATUS_OK) + return status; + + if (write_len) { status = flash_program_write(dest_addr, write_len, data); if (status != NPCX_FLASH_STATUS_OK) @@ -162,8 +247,16 @@ int flash_physical_write(uint32_t offset, uint32_t size, const uint8_t *data) return NPCX_FLASH_STATUS_OK; } -int flash_physical_erase(uint32_t offset, uint32_t size) +static int flash_physical_erase(uint32_t offset, uint32_t size) { + /* Configure fiu */ + flash_init(); + + /* clear flash status registers */ + int status = flash_physical_clear_stsreg(); + if (status != NPCX_FLASH_STATUS_OK) + return status; + /* Alignment has been checked in upper layer */ for (; size > 0; size -= NPCX_FLASH_ERASE_SIZE, offset += NPCX_FLASH_ERASE_SIZE) { @@ -175,7 +268,7 @@ int flash_physical_erase(uint32_t offset, uint32_t size) /* Set erase address */ flash_set_address(offset); /* Start erase */ - flash_execute_cmd(NPCX_CMD_SECTOR_ERASE, NPCX_MASK_CMD_ADR); + flash_execute_cmd(NPCX_CMD_SECTOR_ERASE, NPCX_MASK_CMD_WR_3BYTE); /* Wait erase completed */ status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT); if (status != NPCX_FLASH_STATUS_OK) @@ -185,55 +278,36 @@ int flash_physical_erase(uint32_t offset, uint32_t size) return NPCX_FLASH_STATUS_OK; } -int flash_physical_erase_all(void) +static int flash_physical_erase_all(void) { - /* Enable write */ - int status = flash_write_enable(); - if (status != NPCX_FLASH_STATUS_OK) - return status; - - /* Start erase */ - flash_execute_cmd(NPCX_CMD_CHIP_ERASE, NPCX_MASK_CMD_ONLY); + int status; - /* Wait erase completed */ - status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT); + /* Configure fiu and clear status register if needed */ + flash_init(); + status = flash_physical_clear_stsreg(); if (status != NPCX_FLASH_STATUS_OK) return status; - return NPCX_FLASH_STATUS_OK; -} - -int flash_physical_clear_stsreg(void) -{ /* Enable write */ - int status = flash_write_enable(); + status = flash_write_enable(); if (status != NPCX_FLASH_STATUS_OK) return status; - NPCX_UMA_DB0 = 0x0; - NPCX_UMA_DB1 = 0x0; - - /* Write status register 1/2 */ - flash_execute_cmd(NPCX_CMD_WRITE_STATUS_REG, NPCX_MASK_CMD_WR_2BYTE); + /* Start erase */ + flash_execute_cmd(NPCX_CMD_CHIP_ERASE, NPCX_MASK_CMD_ONLY); - /* Wait writing completed */ + /* Wait erase completed */ status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT); if (status != NPCX_FLASH_STATUS_OK) return status; - /* Read status register 1/2 for checking */ - flash_execute_cmd(NPCX_CMD_READ_STATUS_REG, NPCX_MASK_CMD_RD_1BYTE); - if (NPCX_UMA_DB0 != 0x00) - return NPCX_FLASH_STATUS_FAILED; - flash_execute_cmd(NPCX_CMD_READ_STATUS_REG2, NPCX_MASK_CMD_RD_1BYTE); - if (NPCX_UMA_DB0 != 0x00) - return NPCX_FLASH_STATUS_FAILED; - return NPCX_FLASH_STATUS_OK; } -int flash_get_id(uint32_t *id) +static int flash_get_id(uint32_t *id) { + flash_init(); + flash_execute_cmd(NPCX_CMD_READ_ID, NPCX_MASK_CMD_RD_3BYTE); *id = NPCX_UMA_DB0 << 16 | NPCX_UMA_DB1 << 8 | NPCX_UMA_DB2; @@ -243,7 +317,7 @@ int flash_get_id(uint32_t *id) /*---------------------------------------------------------------------------- * flash loader function *----------------------------------------------------------------------------*/ -uint32_t flashloader_init(struct npcx_flash_params *params) +static uint32_t flashloader_init(struct npcx_flash_params *params) { /* Initialize params buffers */ memset(params, 0, sizeof(struct npcx_flash_params)); @@ -254,30 +328,13 @@ uint32_t flashloader_init(struct npcx_flash_params *params) /*---------------------------------------------------------------------------- * Functions *----------------------------------------------------------------------------*/ -/* flashloader parameter structure */ -__attribute__ ((section(".buffers.g_cfg"))) -volatile struct npcx_flash_params g_cfg; -/* data buffer */ -__attribute__ ((section(".buffers.g_buf"))) -uint8_t g_buf[NPCX_FLASH_LOADER_BUFFER_SIZE]; - -int main(void) +static int main(void) { - uint32_t id; + uint32_t id, status; /* set buffer */ flashloader_init((struct npcx_flash_params *)&g_cfg); - /* Avoid F_CS0 toggles while programming the internal flash. */ - NPCX_SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI); - - /* clear flash status registers */ - int status = flash_physical_clear_stsreg(); - if (status != NPCX_FLASH_STATUS_OK) { - while (1) - g_cfg.sync = status; - } - while (1) { /* wait command*/ while (g_cfg.sync == NPCX_FLASH_LOADER_WAIT) diff --git a/contrib/loaders/flash/npcx/npcx_flash.h b/contrib/loaders/flash/npcx/npcx_flash.h index cc4f1ad506..48e5d82fd3 100644 --- a/contrib/loaders/flash/npcx/npcx_flash.h +++ b/contrib/loaders/flash/npcx/npcx_flash.h @@ -80,6 +80,7 @@ #define NPCX_FIU_DMM_CYC NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x032) #define NPCX_FIU_EXT_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x033) #define NPCX_FIU_UMA_AB0_3 NPCX_HW_DWORD(NPCX_FIU_BASE_ADDR + 0x034) +#define NPCX_FIU_MSR_IE_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x043) /* FIU register fields */ #define NPCX_RESP_CFG_IAD_EN 0 @@ -93,6 +94,7 @@ #define NPCX_UMA_ECTS_SW_CS1 1 #define NPCX_UMA_ECTS_SEC_CS 2 #define NPCX_UMA_ECTS_UMA_LOCK 3 +#define NPCX_FIU_MSR_IE_CFG_UMA_BLOCK 3 /* Flash UMA commands for npcx internal SPI flash */ #define NPCX_CMD_READ_ID 0x9F @@ -130,7 +132,6 @@ #define NPCX_SPI_FLASH_SR1_BUSY (1 << 0) #define NPCX_MASK_CMD_ONLY (0xC0) -#define NPCX_MASK_CMD_ADR (0xC0 | 0x08) #define NPCX_MASK_CMD_ADR_WR (0xC0 | 0x20 | 0x08 | 0x01) #define NPCX_MASK_RD_1BYTE (0xC0 | 0x10 | 0x01) #define NPCX_MASK_RD_2BYTE (0xC0 | 0x10 | 0x02) @@ -143,10 +144,12 @@ #define NPCX_MASK_CMD_WR_ONLY (0xC0 | 0x20) #define NPCX_MASK_CMD_WR_1BYTE (0xC0 | 0x20 | 0x10 | 0x01) #define NPCX_MASK_CMD_WR_2BYTE (0xC0 | 0x20 | 0x10 | 0x02) -#define NPCX_MASK_CMD_WR_ADR (0xC0 | 0x20 | 0x08) +#define NPCX_MASK_CMD_WR_3BYTE (0xC0 | 0x20 | 0x10 | 0x03) +#define NPCX_MASK_CMD_WR_4BYTE (0xC0 | 0x20 | 0x10 | 0x04) /* Flash loader parameters */ struct __attribute__((__packed__)) npcx_flash_params { + uint32_t fiu_ver; /* Flash controller unit version */ uint32_t addr; /* Address in flash */ uint32_t len; /* Number of bytes */ uint32_t cmd; /* Command */ @@ -176,4 +179,10 @@ enum npcx_flash_status { NPCX_FLASH_STATUS_FAILED_TIMEOUT, }; +enum npcx_fiu_ver { + NPCX_FIU_NPCX = 0, + NPCX_FIU_NPCX_V2, + NPCX_FIU_NPCK, +}; + #endif /* OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_H */ diff --git a/contrib/loaders/flash/npcx/npcx_flash_config.h b/contrib/loaders/flash/npcx/npcx_flash_config.h index 9ec1c5e331..4abd23e348 100644 --- a/contrib/loaders/flash/npcx/npcx_flash_config.h +++ b/contrib/loaders/flash/npcx/npcx_flash_config.h @@ -18,7 +18,7 @@ /* NPCX flash loader information */ #define NPCX_FLASH_LOADER_WORKING_ADDR 0x200C0000 #define NPCX_FLASH_LOADER_PARAMS_ADDR NPCX_FLASH_LOADER_WORKING_ADDR -#define NPCX_FLASH_LOADER_PARAMS_SIZE 16 +#define NPCX_FLASH_LOADER_PARAMS_SIZE 20 #define NPCX_FLASH_LOADER_BUFFER_ADDR (NPCX_FLASH_LOADER_PARAMS_ADDR + NPCX_FLASH_LOADER_PARAMS_SIZE) #define NPCX_FLASH_LOADER_BUFFER_SIZE NPCX_FLASH_ERASE_SIZE #define NPCX_FLASH_LOADER_PROGRAM_ADDR (NPCX_FLASH_LOADER_BUFFER_ADDR + NPCX_FLASH_LOADER_BUFFER_SIZE) diff --git a/doc/openocd.texi b/doc/openocd.texi index d07188c4bc..f6f7a0c293 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7193,10 +7193,16 @@ Show information about flash driver. All versions of the NPCX microcontroller families from Nuvoton include internal flash. The NPCX flash driver supports the NPCX family of devices. The driver automatically recognizes the specific version's flash parameters and -autoconfigures itself. The flash bank starts at address 0x64000000. +autoconfigures itself. The flash bank starts at address 0x64000000. An optional additional +parameter sets the FIU version for the bank, with the default FIU is @var{npcx.fiu}. @example + +flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME npcx_v2.fiu + +# FIU defaults to npcx.fiu flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME + @end example @end deffn diff --git a/src/flash/nor/npcx.c b/src/flash/nor/npcx.c index bc84753463..7304a68412 100644 --- a/src/flash/nor/npcx.c +++ b/src/flash/nor/npcx.c @@ -4,6 +4,7 @@ * Copyright (C) 2020 by Nuvoton Technology Corporation * Mulin Chao * Wealian Liao + * Luca Hung */ #ifdef HAVE_CONFIG_H @@ -22,7 +23,6 @@ static const uint8_t npcx_algo[] = { }; #define NPCX_FLASH_TIMEOUT_MS 8000 -#define NPCX_FLASH_BASE_ADDR 0x64000000 /* flash list */ enum npcx_flash_device_index { @@ -33,7 +33,6 @@ enum npcx_flash_device_index { }; struct npcx_flash_bank { - const char *family_name; uint32_t sector_length; bool probed; enum npcx_flash_device_index flash; @@ -44,6 +43,7 @@ struct npcx_flash_bank { uint32_t algo_working_size; uint32_t buffer_addr; uint32_t params_addr; + uint32_t fiu_ver; }; struct npcx_flash_info { @@ -90,7 +90,7 @@ static int npcx_init(struct flash_bank *bank) /* Confirm the defined working address is the area we need to use */ if (npcx_bank->working_area->address != NPCX_FLASH_LOADER_WORKING_ADDR) { - LOG_ERROR("%s: Invalid working address", npcx_bank->family_name); + LOG_TARGET_ERROR(target, "Invalid working address"); LOG_INFO("Hint: Use '-work-area-phys 0x%" PRIx32 "' in your target configuration", NPCX_FLASH_LOADER_WORKING_ADDR); target_free_working_area(target, npcx_bank->working_area); @@ -102,8 +102,7 @@ static int npcx_init(struct flash_bank *bank) retval = target_write_buffer(target, NPCX_FLASH_LOADER_PROGRAM_ADDR, npcx_bank->algo_size, npcx_bank->algo_code); if (retval != ERROR_OK) { - LOG_ERROR("%s: Failed to load flash helper algorithm", - npcx_bank->family_name); + LOG_TARGET_ERROR(target, "Failed to load flash helper algorithm"); target_free_working_area(target, npcx_bank->working_area); npcx_bank->working_area = NULL; return retval; @@ -118,8 +117,7 @@ static int npcx_init(struct flash_bank *bank) NPCX_FLASH_LOADER_PROGRAM_ADDR, 0, &npcx_bank->armv7m_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: Failed to start flash helper algorithm", - npcx_bank->family_name); + LOG_TARGET_ERROR(target, "Failed to start flash helper algorithm"); target_free_working_area(target, npcx_bank->working_area); npcx_bank->working_area = NULL; return retval; @@ -154,7 +152,6 @@ static int npcx_quit(struct flash_bank *bank) static int npcx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr) { struct target *target = bank->target; - struct npcx_flash_bank *npcx_bank = bank->driver_priv; uint32_t status_addr = params_addr + offsetof(struct npcx_flash_params, sync); uint32_t status; int64_t start_ms = timeval_ms(); @@ -172,9 +169,7 @@ static int npcx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr) } while (status == NPCX_FLASH_LOADER_EXECUTE); if (status != NPCX_FLASH_LOADER_WAIT) { - LOG_ERROR("%s: Flash operation failed, status=0x%" PRIx32, - npcx_bank->family_name, - status); + LOG_TARGET_ERROR(target, "Flash operation failed, status (%0x" PRIX32 ") ", status); return ERROR_FAIL; } @@ -197,6 +192,7 @@ static enum npcx_flash_device_index npcx_get_flash_id(struct flash_bank *bank, u return retval; /* Set up algorithm parameters for get flash ID command */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.fiu_ver, npcx_bank->fiu_ver); target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_GET_FLASH_ID); target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT); @@ -250,6 +246,7 @@ static int npcx_probe(struct flash_bank *bank) npcx_bank->buffer_addr = NPCX_FLASH_LOADER_BUFFER_ADDR; npcx_bank->params_addr = NPCX_FLASH_LOADER_PARAMS_ADDR; + int retval = npcx_get_flash_id(bank, &flash_id); if (retval != ERROR_OK) return retval; @@ -264,7 +261,6 @@ static int npcx_probe(struct flash_bank *bank) return ERROR_FAIL; } - bank->base = NPCX_FLASH_BASE_ADDR; bank->num_sectors = num_sectors; bank->size = num_sectors * sector_length; bank->write_start_alignment = 0; @@ -300,7 +296,7 @@ FLASH_BANK_COMMAND_HANDLER(npcx_flash_bank_command) { struct npcx_flash_bank *npcx_bank; - if (CMD_ARGC < 6) + if (CMD_ARGC < 6 || CMD_ARGC > 7) return ERROR_COMMAND_SYNTAX_ERROR; npcx_bank = calloc(1, sizeof(struct npcx_flash_bank)); @@ -309,8 +305,27 @@ FLASH_BANK_COMMAND_HANDLER(npcx_flash_bank_command) return ERROR_FAIL; } + const char *fiu; + if (CMD_ARGC == 6) { + LOG_WARNING("No FIU is selection, using default."); + npcx_bank->fiu_ver = NPCX_FIU_NPCX; + } + + if (CMD_ARGC == 7) { + fiu = CMD_ARGV[6]; + if (strcmp(fiu, "npcx.fiu") == 0) { + npcx_bank->fiu_ver = NPCX_FIU_NPCX; + } else if (strcmp(fiu, "npcx_v2.fiu") == 0) { + npcx_bank->fiu_ver = NPCX_FIU_NPCX_V2; + } else if (strcmp(fiu, "npck.fiu") == 0) { + npcx_bank->fiu_ver = NPCX_FIU_NPCK; + } else { + LOG_ERROR("%s is not a valid fiu", fiu); + return ERROR_TARGET_INVALID; + } + } + /* Initialize private flash information */ - npcx_bank->family_name = "npcx"; npcx_bank->sector_length = NPCX_FLASH_ERASE_SIZE; /* Finish initialization of bank */ @@ -341,6 +356,7 @@ static int npcx_chip_erase(struct flash_bank *bank) return retval; /* Set up algorithm parameters for chip erase command */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.fiu_ver, npcx_bank->fiu_ver); target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_ERASE_ALL); target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT); @@ -397,6 +413,7 @@ static int npcx_erase(struct flash_bank *bank, unsigned int first, return retval; /* Set up algorithm parameters for erase command */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.fiu_ver, npcx_bank->fiu_ver); target_buffer_set_u32(target, (uint8_t *)&algo_params.addr, address); target_buffer_set_u32(target, (uint8_t *)&algo_params.len, length); target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_ERASE_SECTORS); @@ -464,6 +481,7 @@ static int npcx_write(struct flash_bank *bank, const uint8_t *buffer, } /* Update algo parameters for flash write */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.fiu_ver, npcx_bank->fiu_ver); target_buffer_set_u32(target, (uint8_t *)&algo_params.addr, address); target_buffer_set_u32(target, (uint8_t *)&algo_params.len, size); target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT); @@ -502,7 +520,7 @@ static int npcx_info(struct flash_bank *bank, struct command_invocation *cmd) struct npcx_flash_bank *npcx_bank = bank->driver_priv; command_print_sameline(cmd, "%s flash: %s\n", - npcx_bank->family_name, + target_name(bank->target), flash_info[npcx_bank->flash].name); return ERROR_OK; diff --git a/tcl/target/npcx.cfg b/tcl/target/npcx.cfg index 1a21e1f7f5..84bb0b7a53 100644 --- a/tcl/target/npcx.cfg +++ b/tcl/target/npcx.cfg @@ -9,7 +9,7 @@ source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { - set _CHIPNAME NPCX_M4 + set _CHIPNAME npcx } # SWD DAP ID of Nuvoton NPCX Cortex-M4. @@ -27,6 +27,12 @@ if { [info exists WORKAREASIZE] } { set _WORKAREASIZE 0x8000 } +if { [info exists FIUNAME]} { + set _FIUNAME $FIUNAME +} else { + set _FIUNAME npcx.fiu +} + # Debug Adapter Target Settings swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUDAPID dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu @@ -48,4 +54,4 @@ cortex_m reset_config sysresetreq # flash configuration set _FLASHNAME $_CHIPNAME.flash -flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME +flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME $_FIUNAME From d41a204d8224dad66265e694e5ccf3379de0d494 Mon Sep 17 00:00:00 2001 From: Marek Vrbka Date: Thu, 31 Aug 2023 08:30:37 +0200 Subject: [PATCH 21/50] image: fix binary detection for small files Previously, if the image file was less than 9 bytes long, it was assumed to be an error when it could be a binary image file. This patch makes OpenOCD detect these cases as binary files. Change-Id: I5b4dad2b547786246887812ac75907378fe58671 Signed-off-by: Marek Vrbka Reviewed-on: https://review.openocd.org/c/openocd/+/7880 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/target/image.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/target/image.c b/src/target/image.c index f8de7a23e3..ad2d856b54 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -50,12 +50,15 @@ static int autodetect_image_type(struct image *image, const char *url) if (retval != ERROR_OK) return retval; retval = fileio_read(fileio, 9, buffer, &read_bytes); + fileio_close(fileio); - if (retval == ERROR_OK) { - if (read_bytes != 9) - retval = ERROR_FILEIO_OPERATION_FAILED; + /* If the file is smaller than 9 bytes, it can only be bin */ + if (retval == ERROR_OK && read_bytes != 9) { + LOG_DEBUG("Less than 9 bytes in the image file found."); + LOG_DEBUG("BIN image detected."); + image->type = IMAGE_BINARY; + return ERROR_OK; } - fileio_close(fileio); if (retval != ERROR_OK) return retval; @@ -82,8 +85,10 @@ static int autodetect_image_type(struct image *image, const char *url) && (buffer[1] >= '0') && (buffer[1] < '9')) { LOG_DEBUG("S19 image detected."); image->type = IMAGE_SRECORD; - } else + } else { + LOG_DEBUG("BIN image detected."); image->type = IMAGE_BINARY; + } return ERROR_OK; } From 51d4996c5b48e2f871e98af982f7627e527e8683 Mon Sep 17 00:00:00 2001 From: Vincent Fazio Date: Tue, 29 Aug 2023 07:30:23 -0500 Subject: [PATCH 22/50] jtag/drivers/am335xgpio: do not configure push-pull inputs as output Previously, if a pin was configured as ADAPTER_GPIO_INIT_STATE_INPUT and its drive value was ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL, initialize_gpio would configure the pin as an output. The set_gpio_value function is optimized to not set the direction for pins configured as ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL as it only needs to be set once. When initialize_gpio performs this setup, it checked only that the drive value was ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL to set the output direction but did not exclude input pins which have already had their direction set. Now, input pins are ignored when initialize_gpio checks for ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL to set the mode to output. Fixes: ace028262ba0 ("drivers/am335xgpio: Migrate to adapter gpio commands") Change-Id: I9ea502c400ea4ffae37080b9cee891ca9176a47d Signed-off-by: Vincent Fazio Reviewed-on: https://review.openocd.org/c/openocd/+/7877 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Steve Marple --- src/jtag/drivers/am335xgpio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jtag/drivers/am335xgpio.c b/src/jtag/drivers/am335xgpio.c index e641a4fae6..29d410118e 100644 --- a/src/jtag/drivers/am335xgpio.c +++ b/src/jtag/drivers/am335xgpio.c @@ -184,7 +184,8 @@ static void initialize_gpio(enum adapter_gpio_config_index idx) } /* Direction for non push-pull is already set by set_gpio_value() */ - if (adapter_gpio_config[idx].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL) + if (adapter_gpio_config[idx].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL + && adapter_gpio_config[idx].init_state != ADAPTER_GPIO_INIT_STATE_INPUT) AM335XGPIO_SET_OUTPUT(&adapter_gpio_config[idx]); } From 236c54c94a53ff76537a1bf91cfe74a264a2756f Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Tue, 22 Aug 2023 16:24:30 +0300 Subject: [PATCH 23/50] server/gdb_server.c: support unavailable registers According to gdb documentation, `g` and `p` packets can report a register being unavailable by a string of 'x' instead of register's value. Change-Id: I8ef279f1357c2e612f5d3290eb0022c1b47d9fa7 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/7876 Reviewed-by: Marek Vrbka Reviewed-by: Antonio Borneo Reviewed-by: Anatoly Parshintsev Tested-by: jenkins --- src/server/gdb_server.c | 49 +++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 4a4ea53dc3..497f62c429 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1207,6 +1207,27 @@ static void gdb_target_to_reg(struct target *target, } } +/* get register value if needed and fill the buffer accordingly */ +static int gdb_get_reg_value_as_str(struct target *target, char *tstr, struct reg *reg) +{ + int retval = ERROR_OK; + + if (!reg->valid) + retval = reg->type->get(reg); + + const unsigned int len = DIV_ROUND_UP(reg->size, 8) * 2; + switch (retval) { + case ERROR_OK: + gdb_str_to_target(target, tstr, reg); + return ERROR_OK; + case ERROR_TARGET_RESOURCE_NOT_AVAILABLE: + memset(tstr, 'x', len); + tstr[len] = '\0'; + return ERROR_OK; + } + return ERROR_FAIL; +} + static int gdb_get_registers_packet(struct connection *connection, char const *packet, int packet_size) { @@ -1248,16 +1269,11 @@ static int gdb_get_registers_packet(struct connection *connection, for (i = 0; i < reg_list_size; i++) { if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden) continue; - if (!reg_list[i]->valid) { - retval = reg_list[i]->type->get(reg_list[i]); - if (retval != ERROR_OK && gdb_report_register_access_error) { - LOG_DEBUG("Couldn't get register %s.", reg_list[i]->name); - free(reg_packet); - free(reg_list); - return gdb_error(connection, retval); - } + if (gdb_get_reg_value_as_str(target, reg_packet_p, reg_list[i]) != ERROR_OK) { + free(reg_packet); + free(reg_list); + return gdb_error(connection, retval); } - gdb_str_to_target(target, reg_packet_p, reg_list[i]); reg_packet_p += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; } @@ -1369,18 +1385,13 @@ static int gdb_get_register_packet(struct connection *connection, return ERROR_SERVER_REMOTE_CLOSED; } - if (!reg_list[reg_num]->valid) { - retval = reg_list[reg_num]->type->get(reg_list[reg_num]); - if (retval != ERROR_OK && gdb_report_register_access_error) { - LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name); - free(reg_list); - return gdb_error(connection, retval); - } - } - reg_packet = calloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2 + 1, 1); /* plus one for string termination null */ - gdb_str_to_target(target, reg_packet, reg_list[reg_num]); + if (gdb_get_reg_value_as_str(target, reg_packet, reg_list[reg_num]) != ERROR_OK) { + free(reg_packet); + free(reg_list); + return gdb_error(connection, retval); + } gdb_put_packet(connection, reg_packet, DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2); From c4db1960888266972b4e98ae13d533227ea86d29 Mon Sep 17 00:00:00 2001 From: Joshua Nekl Date: Fri, 25 Aug 2023 12:24:54 -0700 Subject: [PATCH 24/50] tcl/interface/ftdi: digilent-hs2.cfg SWD config Add SWD_EN and SWDIO_OE config for Digilent HS2 Change-Id: I3f7479bbe2e518ad6f84bf9eb729b54fee4a0f9b Signed-off-by: Joshua Nekl Reviewed-on: https://review.openocd.org/c/openocd/+/7863 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/interface/ftdi/digilent-hs2.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tcl/interface/ftdi/digilent-hs2.cfg b/tcl/interface/ftdi/digilent-hs2.cfg index e9fe94eb6c..9501c4ad4a 100644 --- a/tcl/interface/ftdi/digilent-hs2.cfg +++ b/tcl/interface/ftdi/digilent-hs2.cfg @@ -8,5 +8,7 @@ ftdi vid_pid 0x0403 0x6014 ftdi channel 0 ftdi layout_init 0x00e8 0x60eb +ftdi layout_signal SWD_EN -data 0x6000 +ftdi layout_signal SWDIO_OE -data 0x20 reset_config none From 3cceec11cd22f96182aff019d7e7ab63a7e944ae Mon Sep 17 00:00:00 2001 From: Joshua Nekl Date: Fri, 1 Sep 2023 16:29:33 -0700 Subject: [PATCH 25/50] tcl/interface/ftdi: Add documentation for HS2 Change-Id: I75d6aa0292bf7ff4ebee8752a5e7a3516500cd04 Signed-off-by: Joshua Nekl Reviewed-on: https://review.openocd.org/c/openocd/+/7881 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/interface/ftdi/digilent-hs2.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tcl/interface/ftdi/digilent-hs2.cfg b/tcl/interface/ftdi/digilent-hs2.cfg index 9501c4ad4a..89c9e4b6c4 100644 --- a/tcl/interface/ftdi/digilent-hs2.cfg +++ b/tcl/interface/ftdi/digilent-hs2.cfg @@ -2,6 +2,10 @@ # this supports JTAG-HS2 (and apparently Nexys4 as well) +# ADBUS5 controls TMS tri-state buffer enable +# ACBUS6=SEL_TMS controls mux to TMS output buffer: 0=TMS 1=TDI +# ACBUS5=SEL_TDO controls mux to TDO input: 0=TDO 1=TMS + adapter driver ftdi ftdi device_desc "Digilent Adept USB Device" ftdi vid_pid 0x0403 0x6014 From 300fe1d405729aa6bd64bc1287c6c45735624092 Mon Sep 17 00:00:00 2001 From: Daniel Goehring Date: Fri, 10 Sep 2021 22:19:08 -0400 Subject: [PATCH 26/50] target/aarch64: add AArch64 mdd and mwd support For ARMv8, add AArch64 mdd and mwd support. AArch32 not supported. Change-Id: I25490471e16943e5a67d7649595d77643aa9a095 Signed-off-by: Daniel Goehring Reviewed-on: https://review.openocd.org/c/openocd/+/7192 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/aarch64.c | 65 +++++++++++++++++++++++++++++++------- src/target/armv8_opcodes.c | 2 ++ src/target/armv8_opcodes.h | 4 +++ 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index d25c7d30e1..db602435cf 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2047,6 +2047,11 @@ static int aarch64_write_cpu_memory_slow(struct target *target, struct arm *arm = &armv8->arm; int retval; + if (size > 4 && arm->core_state != ARM_STATE_AARCH64) { + LOG_ERROR("memory write sizes greater than 4 bytes is only supported for AArch64 state"); + return ERROR_FAIL; + } + armv8_reg_current(arm, 1)->dirty = true; /* change DCC to normal mode if necessary */ @@ -2059,22 +2064,32 @@ static int aarch64_write_cpu_memory_slow(struct target *target, } while (count) { - uint32_t data, opcode; + uint32_t opcode; + uint64_t data; - /* write the data to store into DTRRX */ + /* write the data to store into DTRRX (and DTRTX for 64-bit) */ if (size == 1) data = *buffer; else if (size == 2) data = target_buffer_get_u16(target, buffer); - else + else if (size == 4) data = target_buffer_get_u32(target, buffer); + else + data = target_buffer_get_u64(target, buffer); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DTRRX, data); + armv8->debug_base + CPUV8_DBG_DTRRX, (uint32_t)data); + if (retval == ERROR_OK && size > 4) + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DTRTX, (uint32_t)(data >> 32)); if (retval != ERROR_OK) return retval; if (arm->core_state == ARM_STATE_AARCH64) - retval = dpm->instr_execute(dpm, ARMV8_MRS(SYSTEM_DBG_DTRRX_EL0, 1)); + if (size <= 4) + retval = dpm->instr_execute(dpm, ARMV8_MRS(SYSTEM_DBG_DTRRX_EL0, 1)); + else + retval = dpm->instr_execute(dpm, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 1)); else retval = dpm->instr_execute(dpm, ARMV4_5_MRC(14, 0, 1, 0, 5, 0)); if (retval != ERROR_OK) @@ -2084,8 +2099,11 @@ static int aarch64_write_cpu_memory_slow(struct target *target, opcode = armv8_opcode(armv8, ARMV8_OPC_STRB_IP); else if (size == 2) opcode = armv8_opcode(armv8, ARMV8_OPC_STRH_IP); - else + else if (size == 4) opcode = armv8_opcode(armv8, ARMV8_OPC_STRW_IP); + else + opcode = armv8_opcode(armv8, ARMV8_OPC_STRD_IP); + retval = dpm->instr_execute(dpm, opcode); if (retval != ERROR_OK) return retval; @@ -2226,6 +2244,11 @@ static int aarch64_read_cpu_memory_slow(struct target *target, struct arm *arm = &armv8->arm; int retval; + if (size > 4 && arm->core_state != ARM_STATE_AARCH64) { + LOG_ERROR("memory read sizes greater than 4 bytes is only supported for AArch64 state"); + return ERROR_FAIL; + } + armv8_reg_current(arm, 1)->dirty = true; /* change DCC to normal mode (if necessary) */ @@ -2238,36 +2261,56 @@ static int aarch64_read_cpu_memory_slow(struct target *target, } while (count) { - uint32_t opcode, data; + uint32_t opcode; + uint32_t lower; + uint32_t higher; + uint64_t data; if (size == 1) opcode = armv8_opcode(armv8, ARMV8_OPC_LDRB_IP); else if (size == 2) opcode = armv8_opcode(armv8, ARMV8_OPC_LDRH_IP); - else + else if (size == 4) opcode = armv8_opcode(armv8, ARMV8_OPC_LDRW_IP); + else + opcode = armv8_opcode(armv8, ARMV8_OPC_LDRD_IP); + retval = dpm->instr_execute(dpm, opcode); if (retval != ERROR_OK) return retval; if (arm->core_state == ARM_STATE_AARCH64) - retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 1)); + if (size <= 4) + retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 1)); + else + retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 1)); else retval = dpm->instr_execute(dpm, ARMV4_5_MCR(14, 0, 1, 0, 5, 0)); if (retval != ERROR_OK) return retval; retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DTRTX, &data); + armv8->debug_base + CPUV8_DBG_DTRTX, &lower); + if (retval == ERROR_OK) { + if (size > 4) + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DTRRX, &higher); + else + higher = 0; + } if (retval != ERROR_OK) return retval; + data = (uint64_t)lower | (uint64_t)higher << 32; + if (size == 1) *buffer = (uint8_t)data; else if (size == 2) target_buffer_set_u16(target, buffer, (uint16_t)data); + else if (size == 4) + target_buffer_set_u32(target, buffer, (uint32_t)data); else - target_buffer_set_u32(target, buffer, data); + target_buffer_set_u64(target, buffer, data); /* Advance */ buffer += size; diff --git a/src/target/armv8_opcodes.c b/src/target/armv8_opcodes.c index 7afcc5219e..2635b3ec5f 100644 --- a/src/target/armv8_opcodes.c +++ b/src/target/armv8_opcodes.c @@ -36,9 +36,11 @@ static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = { [ARMV8_OPC_LDRB_IP] = ARMV8_LDRB_IP(1, 0), [ARMV8_OPC_LDRH_IP] = ARMV8_LDRH_IP(1, 0), [ARMV8_OPC_LDRW_IP] = ARMV8_LDRW_IP(1, 0), + [ARMV8_OPC_LDRD_IP] = ARMV8_LDRD_IP(1, 0), [ARMV8_OPC_STRB_IP] = ARMV8_STRB_IP(1, 0), [ARMV8_OPC_STRH_IP] = ARMV8_STRH_IP(1, 0), [ARMV8_OPC_STRW_IP] = ARMV8_STRW_IP(1, 0), + [ARMV8_OPC_STRD_IP] = ARMV8_STRD_IP(1, 0), }; static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index 8c9652bfed..ddb0f9b073 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -155,6 +155,7 @@ #define ARMV8_LDRB_IP(rd, rn) (0x38401400 | (rn << 5) | rd) #define ARMV8_LDRH_IP(rd, rn) (0x78402400 | (rn << 5) | rd) #define ARMV8_LDRW_IP(rd, rn) (0xb8404400 | (rn << 5) | rd) +#define ARMV8_LDRD_IP(rd, rn) (0xf8408400 | (rn << 5) | rd) #define ARMV8_LDRB_IP_T3(rd, rn) (0xf8100b01 | (rn << 16) | (rd << 12)) #define ARMV8_LDRH_IP_T3(rd, rn) (0xf8300b02 | (rn << 16) | (rd << 12)) @@ -163,6 +164,7 @@ #define ARMV8_STRB_IP(rd, rn) (0x38001400 | (rn << 5) | rd) #define ARMV8_STRH_IP(rd, rn) (0x78002400 | (rn << 5) | rd) #define ARMV8_STRW_IP(rd, rn) (0xb8004400 | (rn << 5) | rd) +#define ARMV8_STRD_IP(rd, rn) (0xf8008400 | (rn << 5) | rd) #define ARMV8_STRB_IP_T3(rd, rn) (0xf8000b01 | (rn << 16) | (rd << 12)) #define ARMV8_STRH_IP_T3(rd, rn) (0xf8200b02 | (rn << 16) | (rd << 12)) @@ -200,9 +202,11 @@ enum armv8_opcode { ARMV8_OPC_STRB_IP, ARMV8_OPC_STRH_IP, ARMV8_OPC_STRW_IP, + ARMV8_OPC_STRD_IP, ARMV8_OPC_LDRB_IP, ARMV8_OPC_LDRH_IP, ARMV8_OPC_LDRW_IP, + ARMV8_OPC_LDRD_IP, ARMV8_OPC_NUM, }; From 8bbbff185ff97102f7b0db4f1aee7f4d81a06e7d Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Sep 2023 09:24:59 +0200 Subject: [PATCH 27/50] flash: npcx: fix memory leak in npcx_flash_bank_command Recent commit 62f76b216930 ("flash/nor: add support for Nuvoton NPCX4/K3 series flash") introduces a memory leak for a missing free() on early return for an error. Add the free() on the return path on error. Change-Id: Ica8568a986802e23df2ab7bed4e8cc4bbb6305a5 Signed-off-by: Antonio Borneo Fixes: 62f76b216930 ("flash/nor: add support for Nuvoton NPCX4/K3 series flash") Reviewed-on: https://review.openocd.org/c/openocd/+/7894 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/npcx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/flash/nor/npcx.c b/src/flash/nor/npcx.c index 7304a68412..4a301f1e98 100644 --- a/src/flash/nor/npcx.c +++ b/src/flash/nor/npcx.c @@ -321,6 +321,7 @@ FLASH_BANK_COMMAND_HANDLER(npcx_flash_bank_command) npcx_bank->fiu_ver = NPCX_FIU_NPCK; } else { LOG_ERROR("%s is not a valid fiu", fiu); + free(npcx_bank); return ERROR_TARGET_INVALID; } } From fb52ba4fa1ea4f5bcf4b72ac85af4fe2fada7ee7 Mon Sep 17 00:00:00 2001 From: Fedi Bouzazi Date: Mon, 14 Aug 2023 13:03:31 +0100 Subject: [PATCH 28/50] target/cortex_m: support DWT version 2.1 for Archv8_M MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to Arm®v8-M Architecture Reference Manual: section D1.2.59 DWT_DEVARCH, DWT Device Architecture Register, the field REVISION bits [19:16] defines two DWT architectures revision Signed-off-by: Fedi Bouzazi Change-Id: I948dae0710ac921a7f0fbcef3ccacdae99184fe4 Reviewed-on: https://review.openocd.org/c/openocd/+/7800 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI Reviewed-by: Antonio Borneo --- src/target/cortex_m.c | 3 ++- src/target/cortex_m.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 014ceaebaa..854e8eb586 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1959,7 +1959,8 @@ static int cortex_m_set_watchpoint(struct target *target, struct watchpoint *wat target_write_u32(target, comparator->dwt_comparator_address + 0, comparator->comp); - if ((cortex_m->dwt_devarch & 0x1FFFFF) != DWT_DEVARCH_ARMV8M) { + if ((cortex_m->dwt_devarch & 0x1FFFFF) != DWT_DEVARCH_ARMV8M_V2_0 + && (cortex_m->dwt_devarch & 0x1FFFFF) != DWT_DEVARCH_ARMV8M_V2_1) { uint32_t mask = 0, temp; /* watchpoint params were validated earlier */ diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index b5d1da7f24..065e4d47bc 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -92,7 +92,8 @@ struct cortex_m_part_info { #define DWT_FUNCTION0 0xE0001028 #define DWT_DEVARCH 0xE0001FBC -#define DWT_DEVARCH_ARMV8M 0x101A02 +#define DWT_DEVARCH_ARMV8M_V2_0 0x101A02 +#define DWT_DEVARCH_ARMV8M_V2_1 0x111A02 #define FP_CTRL 0xE0002000 #define FP_REMAP 0xE0002004 From 870769b0ba9f4dae6ada9d8b1a40d75bd83aaa06 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Wed, 31 May 2023 15:16:35 +0100 Subject: [PATCH 29/50] flash/stm32l4x: support STM32WBA5xx devices STM32WBA5x have a single bank flash up to 1MB Change-Id: I3d720e202f0fdd89ecd8aa7224653ca5a7ae187b Signed-off-by: Tarek BOCHKATI Signed-off-by: Erwan Gouriou Reviewed-on: https://review.openocd.org/c/openocd/+/7694 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/flash/nor/stm32l4x.c | 25 +++++++++ src/flash/nor/stm32l4x.h | 1 + tcl/target/stm32wbax.cfg | 106 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 tcl/target/stm32wbax.cfg diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 4414cf5396..96757a931d 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -57,6 +57,9 @@ */ /* STM32WBxxx series for reference. + * + * RM0493 (STM32WBA52x) + * http://www.st.com/resource/en/reference_manual/dm00821869.pdf * * RM0434 (STM32WB55/WB35x) * http://www.st.com/resource/en/reference_manual/dm00318631.pdf @@ -346,6 +349,10 @@ static const struct stm32l4_rev stm32u57_u58xx_revs[] = { { 0x2001, "X" }, { 0x3000, "C" }, }; +static const struct stm32l4_rev stm32wba5x_revs[] = { + { 0x1000, "A" }, +}; + static const struct stm32l4_rev stm32wb1xx_revs[] = { { 0x1000, "A" }, { 0x2000, "B" }, }; @@ -579,6 +586,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x0BFA0000, .otp_size = 512, }, + { + .id = DEVID_STM32WBA5X, + .revs = stm32wba5x_revs, + .num_revs = ARRAY_SIZE(stm32wba5x_revs), + .device_str = "STM32WBA5x", + .max_flash_size_kb = 1024, + .flags = F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x0FF907A0, + .otp_base = 0x0FF90000, + .otp_size = 512, + }, { .id = DEVID_STM32WB1XX, .revs = stm32wb1xx_revs, @@ -1993,6 +2012,12 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; + case DEVID_STM32WBA5X: + /* single bank flash */ + page_size_kb = 8; + num_pages = flash_size_kb / page_size_kb; + stm32l4_info->bank1_sectors = num_pages; + break; case DEVID_STM32WB5XX: case DEVID_STM32WB3XX: /* single bank flash */ diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 278038d763..3dc0909554 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -103,6 +103,7 @@ #define DEVID_STM32L55_L56XX 0x472 #define DEVID_STM32G49_G4AXX 0x479 #define DEVID_STM32U57_U58XX 0x482 +#define DEVID_STM32WBA5X 0x492 #define DEVID_STM32WB1XX 0x494 #define DEVID_STM32WB5XX 0x495 #define DEVID_STM32WB3XX 0x496 diff --git a/tcl/target/stm32wbax.cfg b/tcl/target/stm32wbax.cfg new file mode 100644 index 0000000000..129940720b --- /dev/null +++ b/tcl/target/stm32wbax.cfg @@ -0,0 +1,106 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# script for stm32wbax family + +# +# stm32wba devices support both JTAG and SWD transports. +# +source [find target/swj-dp.tcl] +source [find mem_helper.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME stm32wbax +} + +# Work-area is a space in RAM used for flash programming +# By default use 64kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x10000 +} + +#jtag scan chain +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + if { [using_jtag] } { + set _CPUTAPID 0x6ba00477 + } else { + # SWD IDCODE (single drop, arm) + set _CPUTAPID 0x6ba02477 + } +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +if {[using_jtag]} { + jtag newtap $_CHIPNAME bs -irlen 5 +} + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian little -dap $_CHIPNAME.dap -ap-num 1 + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +flash bank $_CHIPNAME.flash stm32l4x 0x08000000 0 0 0 $_TARGETNAME +flash bank $_CHIPNAME.otp stm32l4x 0x0FF90000 0 0 0 $_TARGETNAME + +# Common knowledges tells JTAG speed should be <= F_CPU/6. +# F_CPU after reset is MSI 4MHz, so use F_JTAG = 500 kHz to stay on +# the safe side. +# +# Note that there is a pretty wide band where things are +# more or less stable, see http://openocd.zylin.com/#/c/3366/ +adapter speed 500 + +adapter srst delay 100 +if {[using_jtag]} { + jtag_ntrst_delay 100 +} + +reset_config srst_nogate + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + +$_TARGETNAME configure -event reset-init { + # CPU comes out of reset with HSION | HSIRDY. + # Use HSI 16 MHz clock, compliant even with VOS == 2. + # 1 WS compliant with VOS == 2 and 16 MHz. + mmw 0x40022000 0x00000001 0x0000000E ;# FLASH_ACR: Latency = 1 + mmw 0x56020C00 0x00000100 0x00000000 ;# RCC_CR |= HSION + mmw 0x56020C1C 0x00000000 0x00000002 ;# RCC_CFGR1: SW=HSI16 + # Boost JTAG frequency + adapter speed 4000 +} + +$_TARGETNAME configure -event reset-start { + # Reset clock is HSI (16 MHz) + adapter speed 2000 +} + +$_TARGETNAME configure -event examine-end { + # Enable debug during low power modes (uses more power) + # DBGMCU_CR |= DBG_STANDBY | DBG_STOP + mmw 0xE0042004 0x00000006 0 + + # Stop watchdog counters during halt + # DBGMCU_APB1LFZR |= DBG_IWDG_STOP | DBG_WWDG_STOP + mmw 0xE0042008 0x00001800 0 +} + +tpiu create $_CHIPNAME.tpiu -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0xE0040000 + +lappend _telnet_autocomplete_skip _proc_pre_enable_$_CHIPNAME.tpiu +proc _proc_pre_enable_$_CHIPNAME.tpiu {_targetname} { + targets $_targetname +} + +$_CHIPNAME.tpiu configure -event pre-enable "_proc_pre_enable_$_CHIPNAME.tpiu $_TARGETNAME" From 040757b7e6d7bc4951af3d683f774f0660d002b5 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 5 Sep 2023 18:32:57 +0200 Subject: [PATCH 30/50] flash/nor/at91sam7: fix flash bank allocation at91sam7 flash driver allocates a flash bank based on detected flash structure. Use calloc() instead of malloc() - struct flash_bank has to be zeroed. While on this: Return error in case of struct flash_bank or driver_priv allocation fail. Set default_padded_value and erased_value. Use strdup() on bank->name, pointer is freed in flash_free_all_banks() Signed-off-by: Tomas Vanek Change-Id: Id890496bfbadb7970ef583256aa4f30a7bff832f Reviewed-on: https://review.openocd.org/c/openocd/+/7884 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/at91sam7.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c index 8d8cf22268..8bb2994ed1 100644 --- a/src/flash/nor/at91sam7.c +++ b/src/flash/nor/at91sam7.c @@ -560,11 +560,22 @@ static int at91sam7_read_part_info(struct flash_bank *bank) if (bnk > 0) { if (!t_bank->next) { /* create a new flash bank element */ - struct flash_bank *fb = malloc(sizeof(struct flash_bank)); + struct flash_bank *fb = calloc(sizeof(struct flash_bank), 1); + if (!fb) { + LOG_ERROR("No memory for flash bank"); + return ERROR_FAIL; + } fb->target = target; fb->driver = bank->driver; + fb->default_padded_value = 0xff; + fb->erased_value = 0xff; fb->driver_priv = malloc(sizeof(struct at91sam7_flash_bank)); - fb->name = "sam7_probed"; + if (!fb->driver_priv) { + free(fb); + LOG_ERROR("No memory for flash driver priv"); + return ERROR_FAIL; + } + fb->name = strdup("sam7_probed"); fb->next = NULL; /* link created bank in 'flash_banks' list */ @@ -738,11 +749,22 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) if (bnk > 0) { if (!t_bank->next) { /* create a new bank element */ - struct flash_bank *fb = malloc(sizeof(struct flash_bank)); + struct flash_bank *fb = calloc(sizeof(struct flash_bank), 1); + if (!fb) { + LOG_ERROR("No memory for flash bank"); + return ERROR_FAIL; + } fb->target = target; fb->driver = bank->driver; + fb->default_padded_value = 0xff; + fb->erased_value = 0xff; fb->driver_priv = malloc(sizeof(struct at91sam7_flash_bank)); - fb->name = "sam7_probed"; + if (!fb->driver_priv) { + free(fb); + LOG_ERROR("No memory for flash driver priv"); + return ERROR_FAIL; + } + fb->name = strdup("sam7_probed"); fb->next = NULL; /* link created bank in 'flash_banks' list */ From c20cb28fafaa7c255adccfa3040998fc29628ab9 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 5 Sep 2023 18:52:38 +0200 Subject: [PATCH 31/50] flash/nor: remove useless bank->next = NULL struct flash_bank must be zeroed anyway, calloc() is always used. Signed-off-by: Tomas Vanek Change-Id: I7ab3b9c66f99688c6095a0a547a05448c9e37d68 Reviewed-on: https://review.openocd.org/c/openocd/+/7885 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/at91sam7.c | 2 -- src/flash/nor/cc26xx.c | 1 - src/flash/nor/cc3220sf.c | 1 - src/flash/nor/npcx.c | 1 - 4 files changed, 5 deletions(-) diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c index 8bb2994ed1..6879a1bf23 100644 --- a/src/flash/nor/at91sam7.c +++ b/src/flash/nor/at91sam7.c @@ -576,7 +576,6 @@ static int at91sam7_read_part_info(struct flash_bank *bank) return ERROR_FAIL; } fb->name = strdup("sam7_probed"); - fb->next = NULL; /* link created bank in 'flash_banks' list */ t_bank->next = fb; @@ -765,7 +764,6 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) return ERROR_FAIL; } fb->name = strdup("sam7_probed"); - fb->next = NULL; /* link created bank in 'flash_banks' list */ t_bank->next = fb; diff --git a/src/flash/nor/cc26xx.c b/src/flash/nor/cc26xx.c index 6256ba6e71..54d61421ce 100644 --- a/src/flash/nor/cc26xx.c +++ b/src/flash/nor/cc26xx.c @@ -261,7 +261,6 @@ FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command) /* Finish initialization of bank */ bank->driver_priv = cc26xx_bank; - bank->next = NULL; return ERROR_OK; } diff --git a/src/flash/nor/cc3220sf.c b/src/flash/nor/cc3220sf.c index 432a393f8b..74cb7aea57 100644 --- a/src/flash/nor/cc3220sf.c +++ b/src/flash/nor/cc3220sf.c @@ -96,7 +96,6 @@ FLASH_BANK_COMMAND_HANDLER(cc3220sf_flash_bank_command) /* Finish initialization of flash bank */ bank->driver_priv = cc3220sf_bank; - bank->next = NULL; return ERROR_OK; } diff --git a/src/flash/nor/npcx.c b/src/flash/nor/npcx.c index 4a301f1e98..8309630d7c 100644 --- a/src/flash/nor/npcx.c +++ b/src/flash/nor/npcx.c @@ -331,7 +331,6 @@ FLASH_BANK_COMMAND_HANDLER(npcx_flash_bank_command) /* Finish initialization of bank */ bank->driver_priv = npcx_bank; - bank->next = NULL; return ERROR_OK; } From db1bbbf6a446df78a5da50199e209f83fd278c8d Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 6 Sep 2023 10:10:20 -0500 Subject: [PATCH 32/50] tcl/target/ti_k3: Set _CHIPNAME in one place $_soc is set per platform, no point in duplicating _CHIPNAME to explicitly set the information provided by $_CHIPNAME itself. So move it out after the check for CHIP_NAME Signed-off-by: Nishanth Menon Change-Id: I60d30d6a9a2ce352f66c5bc03075e4ba638e3062 Reviewed-on: https://review.openocd.org/c/openocd/+/7889 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/ti_k3.cfg | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index f0881cdff7..ffba478e76 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -63,7 +63,6 @@ set _gp_mcu_ap_unlock_offsets {0xf0 0x60} # Set configuration overrides for each SOC switch $_soc { am654 { - set _CHIPNAME am654 set _K3_DAP_TAPID 0x0bb5a02f # AM654 has 2 clusters of 2 A53 cores each. @@ -78,7 +77,6 @@ switch $_soc { set _sysctrl_ap_unlock_offsets {0xf0 0x50} } am642 { - set _CHIPNAME am642 set _K3_DAP_TAPID 0x0bb3802f # AM642 has 1 clusters of 2 A53 cores each. @@ -97,7 +95,6 @@ switch $_soc { set _gp_mcu_cores 1 } am625 { - set _CHIPNAME am625 set _K3_DAP_TAPID 0x0bb7e02f # AM625 has 1 clusters of 4 A53 cores. @@ -132,7 +129,6 @@ switch $_soc { set _dmem_emu_ap_list 1 } am62a7 { - set _CHIPNAME am62a7 set _K3_DAP_TAPID 0x0bb8d02f # AM62a7 has 1 clusters of 4 A53 cores. @@ -153,7 +149,6 @@ switch $_soc { set _sysctrl_ap_unlock_offsets {0xf0 0x78} } j721e { - set _CHIPNAME j721e set _K3_DAP_TAPID 0x0bb6402f # J721E has 1 cluster of 2 A72 cores. set _armv8_cpu_name a72 @@ -173,7 +168,6 @@ switch $_soc { set _dmem_emu_ap_list 1 } j7200 { - set _CHIPNAME j7200 set _K3_DAP_TAPID 0x0bb6d02f # J7200 has 1 cluster of 2 A72 cores. @@ -189,7 +183,6 @@ switch $_soc { set CM3_CTIBASE {0x20001000} } j721s2 { - set _CHIPNAME j721s2 set _K3_DAP_TAPID 0x0bb7502f # J721s2 has 1 cluster of 2 A72 cores. @@ -213,6 +206,8 @@ switch $_soc { } } +set _CHIPNAME $_soc + swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_K3_DAP_TAPID -ignore-version dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu From d2f86dfd05230931fc56a412a6cf5f6265b8562b Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 6 Sep 2023 07:59:23 -0500 Subject: [PATCH 33/50] tcl/target/ti_k3: Add J784s4 SoC Add support for the TI K3 family J784S4/AM69 SoC. For further details, see http://www.ti.com/lit/zip/spruj52 Signed-off-by: Nishanth Menon Change-Id: I3c899aed0cb79ab8bbf8077ca6dfe0636cf72288 Reviewed-on: https://review.openocd.org/c/openocd/+/7890 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/ti_k3.cfg | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index ffba478e76..beb98edca7 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -10,6 +10,8 @@ # Has 2 ARMV8 Cores and 4 R5 Cores and an M3 # * J721S2: https://www.ti.com/lit/pdf/spruj28 # Has 2 ARMV8 Cores and 6 R5 Cores and an M4F +# * J784S4/AM69: http://www.ti.com/lit/zip/spruj52 +# Has 8 ARMV8 Cores and 8 R5 Cores # * AM642: https://www.ti.com/lit/pdf/spruim2 # Has 2 ARMV8 Cores and 4 R5 Cores, M4F and an M3 # * AM625: https://www.ti.com/lit/pdf/spruiv7a @@ -201,6 +203,37 @@ switch $_soc { set _gp_mcu_cores 1 set _gp_mcu_ap_unlock_offsets {0xf0 0x7c} } + j784s4 { + set _K3_DAP_TAPID 0x0bb8002f + + # j784s4 has 2 cluster of 4 A72 cores each. + set _armv8_cpu_name a72 + set _armv8_cores 8 + set ARMV8_DBGBASE {0x90410000 0x90510000 0x90610000 0x90710000 + 0x90810000 0x90910000 0x90a10000 0x90b10000} + set ARMV8_CTIBASE {0x90420000 0x90520000 0x90620000 0x90720000 + 0x90820000 0x90920000 0x90a20000 0x90b20000} + + # J721s2 has 4 clusters of 2 R5 cores each. + set _r5_cores 8 + set R5_DBGBASE {0x9d010000 0x9d012000 + 0x9d410000 0x9d412000 + 0x9d510000 0x9d512000 + 0x9d610000 0x9d612000} + set R5_CTIBASE {0x9d018000 0x9d019000 + 0x9d418000 0x9d419000 + 0x9d518000 0x9d519000 + 0x9d618000 0x9d619000} + set R5_NAMES {mcu_r5.0 mcu_r5.1 + main0_r5.0 main0_r5.1 + main1_r5.0 main1_r5.1 + main2_r5.0 main2_r5.1} + + # sysctrl CTI base + set CM3_CTIBASE {0x20001000} + # Sysctrl power-ap unlock offsets + set _sysctrl_ap_unlock_offsets {0xf0 0x78} + } default { echo "'$_soc' is invalid!" } From d8575ab8ab025af78b5b27ad575e4104b4cce520 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 6 Sep 2023 08:07:16 -0500 Subject: [PATCH 34/50] tcl/board: Add TI j784s4evm config Add basic connection details with J784S4 SK/EVM For further details, see: Texas Instruments J784S4 EVM: https://www.ti.com/tool/J784S4XEVM Texas Instruments SK-AM69: https://www.ti.com/tool/SK-AM69 Signed-off-by: Nishanth Menon Change-Id: I09c8a193d53e13b27adb5a6d01f6d937d6be49a1 Reviewed-on: https://review.openocd.org/c/openocd/+/7891 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/board/ti_j784s4evm.cfg | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tcl/board/ti_j784s4evm.cfg diff --git a/tcl/board/ti_j784s4evm.cfg b/tcl/board/ti_j784s4evm.cfg new file mode 100644 index 0000000000..d23dc8ce67 --- /dev/null +++ b/tcl/board/ti_j784s4evm.cfg @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments J784S4 EVM: https://www.ti.com/tool/J784S4XEVM +# Texas Instruments SK-AM69: https://www.ti.com/tool/SK-AM69 +# + +# J784S4/AM69 SK/EVM has an xds110 onboard. +source [find interface/xds110.cfg] + +transport select jtag + +# default JTAG configuration has only SRST and no TRST +reset_config srst_only srst_push_pull + +# delay after SRST goes inactive +adapter srst delay 20 + +if { ![info exists SOC] } { + set SOC j784s4 +} + +source [find target/ti_k3.cfg] + +adapter speed 2500 From a7b77ac84f86dbdc447fcbf7822cb240b3916008 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 6 Sep 2023 10:21:09 -0500 Subject: [PATCH 35/50] tcl/target/ti_k3: Add AM62P SoC Add support for the TI K3 family AM62P SoC. This SoC is built on the same base of AM62A7, so reuse the configuration with the exception of the JTAG ID and the actual name used for the R5 core (moved from main domain to wakeup domain). For further details, see https://www.ti.com/lit/pdf/spruj83 Signed-off-by: Nishanth Menon Change-Id: I3a80be9e71204ed7697e51ac1ad488ef405744ef Reviewed-on: https://review.openocd.org/c/openocd/+/7892 Reviewed-by: Bryan Brattlof Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/ti_k3.cfg | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index beb98edca7..01e11c69f7 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -18,6 +18,8 @@ # Has 4 ARMV8 Cores and 1 R5 Core and an M4F # * AM62a7: https://www.ti.com/lit/pdf/spruj16a # Has 4 ARMV8 Cores and 2 R5 Cores +# * AM62P: https://www.ti.com/lit/pdf/spruj83 +# Has 4 ARMV8 Cores and 2 R5 Cores # source [find target/swj-dp.tcl] @@ -130,16 +132,17 @@ switch $_soc { set _dmem_emu_base_address_map_to 0x1d500000 set _dmem_emu_ap_list 1 } + am62p - am62a7 { set _K3_DAP_TAPID 0x0bb8d02f - # AM62a7 has 1 clusters of 4 A53 cores. + # AM62a7/AM62P has 1 cluster of 4 A53 cores. set _armv8_cpu_name a53 set _armv8_cores 4 set ARMV8_DBGBASE {0x90010000 0x90110000 0x90210000 0x90310000} set ARMV8_CTIBASE {0x90020000 0x90120000 0x90220000 0x90320000} - # AM62a7 has 2 cluster of 1 R5s core. + # AM62a7/AM62P has 2 cluster of 1 R5 core. set _r5_cores 2 set R5_NAMES {main0_r5.0 mcu0_r5.0} set R5_DBGBASE {0x9d410000 0x9d810000} @@ -149,6 +152,12 @@ switch $_soc { set CM3_CTIBASE {0x20001000} # Sysctrl power-ap unlock offsets set _sysctrl_ap_unlock_offsets {0xf0 0x78} + + # Overrides for am62p + if { "$_soc" == "am62p" } { + set _K3_DAP_TAPID 0x0bb9d02f + set R5_NAMES {wkup0_r5.0 mcu0_r5.0} + } } j721e { set _K3_DAP_TAPID 0x0bb6402f From 30375c6439ee97f60d729db747f01fb4eb2cf495 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 6 Sep 2023 10:26:48 -0500 Subject: [PATCH 36/50] tcl/board: Add TI am62pevm config Add basic connection details with AM62P SK/EVM For further details, see: https://www.ti.com/lit/zip/sprr487 Signed-off-by: Nishanth Menon Change-Id: I1ba5e0c7627cf09cc8c221701bc44f73523a4574 Reviewed-on: https://review.openocd.org/c/openocd/+/7893 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Bryan Brattlof --- tcl/board/ti_am62pevm.cfg | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tcl/board/ti_am62pevm.cfg diff --git a/tcl/board/ti_am62pevm.cfg b/tcl/board/ti_am62pevm.cfg new file mode 100644 index 0000000000..2322b3d943 --- /dev/null +++ b/tcl/board/ti_am62pevm.cfg @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments SK-AM62P: https://www.ti.com/lit/zip/sprr487 +# + +# AM62P SK/EVM has an xds110 onboard. +source [find interface/xds110.cfg] + +transport select jtag + +# default JTAG configuration has only SRST and no TRST +reset_config srst_only srst_push_pull + +# delay after SRST goes inactive +adapter srst delay 20 + +if { ![info exists SOC] } { + set SOC am62p +} + +source [find target/ti_k3.cfg] + +adapter speed 2500 From fe5ed48f40e4f1b36d74900d0d9b410affea6bdb Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Fri, 24 Feb 2023 15:57:30 +0100 Subject: [PATCH 37/50] jtagspi/pld: add interface to get support from pld drivers Jtagspi is using a proxy bitstream to "connect" JTAG to the SPI pins. This is not possible with all FPGA vendors/families. In this cases a dedicated procedure is needed to establish such a connection. This patch adds a jtagspi-mode for these cases. It also adds the needed interfaces to jtagspi and the pld-driver so the driver can select the mode and provide the necessary procedures. For the cases where a proxy bitstream is needed, the pld driver will select the mode and provide instruction code needed in this case. Change-Id: I9563f26739589157b39a3664a73d91152cd13f77 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7822 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 56 ++++++++++++++----- src/flash/nor/jtagspi.c | 119 ++++++++++++++++++++++++++++++---------- src/pld/pld.c | 91 +++++++++++++++++++++++++++++- src/pld/pld.h | 14 +++++ tcl/cpld/jtagspi.cfg | 12 +++- 5 files changed, 245 insertions(+), 47 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index f6f7a0c293..7ad48c8629 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5900,24 +5900,42 @@ flash bank $_FLASHNAME cfi 0x00000000 0x02000000 2 4 $_TARGETNAME @c "cfi part_id" disabled @end deffn +@anchor{jtagspi} @deffn {Flash Driver} {jtagspi} @cindex Generic JTAG2SPI driver @cindex SPI @cindex jtagspi @cindex bscan_spi Several FPGAs and CPLDs can retrieve their configuration (bitstream) from a -SPI flash connected to them. To access this flash from the host, the device -is first programmed with a special proxy bitstream that -exposes the SPI flash on the device's JTAG interface. The flash can then be -accessed through JTAG. +SPI flash connected to them. To access this flash from the host, some FPGA +device provides dedicated JTAG instructions, while other FPGA devices should +be programmed with a special proxy bitstream that exposes the SPI flash on +the device's JTAG interface. The flash can then be accessed through JTAG. -Since signaling between JTAG and SPI is compatible, all that is required for +Since signalling between JTAG and SPI is compatible, all that is required for a proxy bitstream is to connect TDI-MOSI, TDO-MISO, TCK-CLK and activate -the flash chip select when the JTAG state machine is in SHIFT-DR. Such -a bitstream for several Xilinx FPGAs can be found in +the flash chip select when the JTAG state machine is in SHIFT-DR. + +Such a bitstream for several Xilinx FPGAs can be found in @file{contrib/loaders/flash/fpga/xilinx_bscan_spi.py}. It requires @uref{https://github.com/m-labs/migen, migen} and a Xilinx toolchain to build. +This mechanism with a proxy bitstream can also be used for FPGAs from Intel and +Efinix. FPGAs from Lattice and Cologne Chip have dedicated JTAG instructions +and procedure to connect the JTAG to the SPI signals and don't need a proxy +bitstream. Support for these devices with dedicated procedure is provided by +the pld drivers. For convenience the PLD drivers will provide the USERx code +for FPGAs with a proxy bitstream. Currently the following PLD drivers are able +to support jtagspi: +@itemize +@item Efinix: proxy-bitstream +@item Gatemate: dedicated procedure +@item Intel/Altera: proxy-bitstream +@item Lattice: dedicated procedure supporting ECP2, ECP3, ECP5, Certus and Certus Pro devices +@item AMD/Xilinx: proxy-bitstream +@end itemize + + This flash bank driver requires a target on a JTAG tap and will access that tap directly. Since no support from the target is needed, the target can be a "testee" dummy. Since the target does not expose the flash memory @@ -5935,14 +5953,25 @@ command, see below. @item @var{ir} ... is loaded into the JTAG IR to map the flash as the JTAG DR. For the bitstreams generated from @file{xilinx_bscan_spi.py} this is the @var{USER1} instruction. -@end itemize +@example +target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap +set _USER1_INSTR_CODE 0x02 +flash bank $_FLASHNAME jtagspi 0x0 0 0 0 \ + $_TARGETNAME $_USER1_INSTR_CODE +@end example + +@item The option @option{-pld} @var{name} is used to have support from the +PLD driver of pld device @var{name}. The name is the name of the pld device +given during creation of the pld device. +Pld device names are shown by the @command{pld devices} command. @example -target create $_TARGETNAME testee -chain-position $_CHIPNAME.fpga -set _XILINX_USER1 0x02 -flash bank $_FLASHNAME spi 0x0 0 0 0 \ - $_TARGETNAME $_XILINX_USER1 +target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap +set _JTAGSPI_CHAIN_ID $_CHIPNAME.pld +flash bank $_FLASHNAME jtagspi 0x0 0 0 0 \ + $_TARGETNAME -pld $_JTAGSPI_CHAIN_ID @end example +@end itemize @deffn Command {jtagspi set} bank_id name total_size page_size read_cmd unused pprg_cmd mass_erase_cmd sector_size sector_erase_cmd Sets flash parameters: @var{name} human readable string, @var{total_size} @@ -8668,7 +8697,8 @@ Accordingly, both are called PLDs here. As it does for JTAG TAPs, debug targets, and flash chips (both NOR and NAND), OpenOCD maintains a list of PLDs available for use in various commands. -Also, each such PLD requires a driver. +Also, each such PLD requires a driver. PLD drivers may also be needed to program +SPI flash connected to the FPGA to store the bitstream (@xref{jtagspi} for details). They are referenced by the name which was given when the pld was created or the number shown by the @command{pld devices} command. diff --git a/src/flash/nor/jtagspi.c b/src/flash/nor/jtagspi.c index 6bb3af9b7d..4b975390be 100644 --- a/src/flash/nor/jtagspi.c +++ b/src/flash/nor/jtagspi.c @@ -12,6 +12,7 @@ #include #include #include +#include #define JTAGSPI_MAX_TIMEOUT 3000 @@ -21,19 +22,44 @@ struct jtagspi_flash_bank { struct flash_device dev; char devname[32]; bool probed; - bool always_4byte; /* use always 4-byte address except for basic read 0x03 */ - uint32_t ir; - unsigned int addr_len; /* address length in bytes */ + bool always_4byte; /* use always 4-byte address except for basic read 0x03 */ + unsigned int addr_len; /* address length in bytes */ + struct pld_device *pld_device; /* if not NULL, the PLD has special instructions for JTAGSPI */ + uint32_t ir; /* when !pld_device, this instruction code is used in + jtagspi_set_user_ir to connect through a proxy bitstream */ }; FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command) { - struct jtagspi_flash_bank *info; - if (CMD_ARGC < 7) return ERROR_COMMAND_SYNTAX_ERROR; - info = malloc(sizeof(struct jtagspi_flash_bank)); + unsigned int ir = 0; + struct pld_device *device = NULL; + if (strcmp(CMD_ARGV[6], "-pld") == 0) { + if (CMD_ARGC < 8) + return ERROR_COMMAND_SYNTAX_ERROR; + device = get_pld_device_by_name_or_numstr(CMD_ARGV[7]); + if (device) { + bool has_jtagspi_instruction = false; + int retval = pld_has_jtagspi_instruction(device, &has_jtagspi_instruction); + if (retval != ERROR_OK) + return retval; + if (!has_jtagspi_instruction) { + retval = pld_get_jtagspi_userircode(device, &ir); + if (retval != ERROR_OK) + return retval; + device = NULL; + } + } else { + LOG_ERROR("pld device '#%s' is out of bounds or unknown", CMD_ARGV[7]); + return ERROR_FAIL; + } + } else { + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], ir); + } + + struct jtagspi_flash_bank *info = calloc(1, sizeof(struct jtagspi_flash_bank)); if (!info) { LOG_ERROR("no memory for flash bank info"); return ERROR_FAIL; @@ -47,18 +73,19 @@ FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command) } info->tap = bank->target->tap; info->probed = false; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], info->ir); + + info->ir = ir; + info->pld_device = device; return ERROR_OK; } -static void jtagspi_set_ir(struct flash_bank *bank) +static void jtagspi_set_user_ir(struct jtagspi_flash_bank *info) { - struct jtagspi_flash_bank *info = bank->driver_priv; struct scan_field field; uint8_t buf[4] = { 0 }; - LOG_DEBUG("loading jtagspi ir"); + LOG_DEBUG("loading jtagspi ir(0x%" PRIx32 ")", info->ir); buf_set_u32(buf, 0, info->tap->ir_length, info->ir); field.num_bits = info->tap->ir_length; field.out_value = buf; @@ -79,6 +106,7 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd, assert(data_buffer || data_len == 0); struct scan_field fields[6]; + struct jtagspi_flash_bank *info = bank->driver_priv; LOG_DEBUG("cmd=0x%02x write_len=%d data_len=%d", cmd, write_len, data_len); @@ -87,22 +115,34 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd, if (is_read) data_len = -data_len; + unsigned int facing_read_bits = 0; + unsigned int trailing_write_bits = 0; + + if (info->pld_device) { + int retval = pld_get_jtagspi_stuff_bits(info->pld_device, &facing_read_bits, &trailing_write_bits); + if (retval != ERROR_OK) + return retval; + } + int n = 0; const uint8_t marker = 1; - fields[n].num_bits = 1; - fields[n].out_value = ▮ - fields[n].in_value = NULL; - n++; - - /* transfer length = cmd + address + read/write, - * -1 due to the counter implementation */ uint8_t xfer_bits[4]; - h_u32_to_be(xfer_bits, ((sizeof(cmd) + write_len + data_len) * CHAR_BIT) - 1); - flip_u8(xfer_bits, xfer_bits, sizeof(xfer_bits)); - fields[n].num_bits = sizeof(xfer_bits) * CHAR_BIT; - fields[n].out_value = xfer_bits; - fields[n].in_value = NULL; - n++; + if (!info->pld_device) { /* mode == JTAGSPI_MODE_PROXY_BITSTREAM */ + facing_read_bits = jtag_tap_count_enabled(); + fields[n].num_bits = 1; + fields[n].out_value = ▮ + fields[n].in_value = NULL; + n++; + + /* transfer length = cmd + address + read/write, + * -1 due to the counter implementation */ + h_u32_to_be(xfer_bits, ((sizeof(cmd) + write_len + data_len) * CHAR_BIT) - 1); + flip_u8(xfer_bits, xfer_bits, sizeof(xfer_bits)); + fields[n].num_bits = sizeof(xfer_bits) * CHAR_BIT; + fields[n].out_value = xfer_bits; + fields[n].in_value = NULL; + n++; + } flip_u8(&cmd, &cmd, sizeof(cmd)); fields[n].num_bits = sizeof(cmd) * CHAR_BIT; @@ -120,10 +160,12 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd, if (data_len > 0) { if (is_read) { - fields[n].num_bits = jtag_tap_count_enabled(); - fields[n].out_value = NULL; - fields[n].in_value = NULL; - n++; + if (facing_read_bits) { + fields[n].num_bits = facing_read_bits; + fields[n].out_value = NULL; + fields[n].in_value = NULL; + n++; + } fields[n].out_value = NULL; fields[n].in_value = data_buffer; @@ -135,16 +177,33 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd, fields[n].num_bits = data_len * CHAR_BIT; n++; } + if (!is_read && trailing_write_bits) { + fields[n].num_bits = trailing_write_bits; + fields[n].out_value = NULL; + fields[n].in_value = NULL; + n++; + } + + if (info->pld_device) { + int retval = pld_connect_spi_to_jtag(info->pld_device); + if (retval != ERROR_OK) + return retval; + } else { + jtagspi_set_user_ir(info); + } - jtagspi_set_ir(bank); /* passing from an IR scan to SHIFT-DR clears BYPASS registers */ - struct jtagspi_flash_bank *info = bank->driver_priv; jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE); int retval = jtag_execute_queue(); + if (retval != ERROR_OK) + return retval; if (is_read) flip_u8(data_buffer, data_buffer, data_len); - return retval; + + if (info->pld_device) + return pld_disconnect_spi_from_jtag(info->pld_device); + return ERROR_OK; } COMMAND_HANDLER(jtagspi_handle_set) diff --git a/src/pld/pld.c b/src/pld/pld.c index c375418a9d..81fb0c4632 100644 --- a/src/pld/pld.c +++ b/src/pld/pld.c @@ -69,8 +69,95 @@ struct pld_device *get_pld_device_by_name_or_numstr(const char *str) return get_pld_device_by_num(dev_num); } -/* @deffn {Config Command} {pld create} pld_name driver -chain-position tap_name [options] -*/ + +int pld_has_jtagspi_instruction(struct pld_device *pld_device, bool *has_instruction) +{ + *has_instruction = false; /* default is using a proxy bitstream */ + + if (!pld_device) + return ERROR_FAIL; + + struct pld_driver *pld_driver = pld_device->driver; + if (!pld_driver) { + LOG_ERROR("pld device has no associated driver"); + return ERROR_FAIL; + } + + if (pld_driver->has_jtagspi_instruction) + return pld_driver->has_jtagspi_instruction(pld_device, has_instruction); + /* else, take the default (proxy bitstream) */ + return ERROR_OK; +} + +int pld_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir) +{ + if (!pld_device) + return ERROR_FAIL; + + struct pld_driver *pld_driver = pld_device->driver; + if (!pld_driver) { + LOG_ERROR("pld device has no associated driver"); + return ERROR_FAIL; + } + + if (pld_driver->get_jtagspi_userircode) + return pld_driver->get_jtagspi_userircode(pld_device, ir); + + return ERROR_FAIL; +} + +int pld_get_jtagspi_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits, + unsigned int *trailing_write_bits) +{ + if (!pld_device) + return ERROR_FAIL; + + struct pld_driver *pld_driver = pld_device->driver; + if (!pld_driver) { + LOG_ERROR("pld device has no associated driver"); + return ERROR_FAIL; + } + + if (pld_driver->get_stuff_bits) + return pld_driver->get_stuff_bits(pld_device, facing_read_bits, trailing_write_bits); + + return ERROR_OK; +} + +int pld_connect_spi_to_jtag(struct pld_device *pld_device) +{ + if (!pld_device) + return ERROR_FAIL; + + struct pld_driver *pld_driver = pld_device->driver; + if (!pld_driver) { + LOG_ERROR("pld device has no associated driver"); + return ERROR_FAIL; + } + + if (pld_driver->connect_spi_to_jtag) + return pld_driver->connect_spi_to_jtag(pld_device); + + return ERROR_FAIL; +} + +int pld_disconnect_spi_from_jtag(struct pld_device *pld_device) +{ + if (!pld_device) + return ERROR_FAIL; + + struct pld_driver *pld_driver = pld_device->driver; + if (!pld_driver) { + LOG_ERROR("pld device has no associated driver"); + return ERROR_FAIL; + } + + if (pld_driver->disconnect_spi_from_jtag) + return pld_driver->disconnect_spi_from_jtag(pld_device); + + return ERROR_FAIL; +} + COMMAND_HANDLER(handle_pld_create_command) { if (CMD_ARGC < 2) diff --git a/src/pld/pld.h b/src/pld/pld.h index b736e6ae20..5e2fcd20cc 100644 --- a/src/pld/pld.h +++ b/src/pld/pld.h @@ -20,12 +20,26 @@ struct pld_ipdbg_hub { unsigned int user_ir_code; }; +int pld_has_jtagspi_instruction(struct pld_device *device, bool *has_instruction); +int pld_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir); + +int pld_get_jtagspi_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits, + unsigned int *trailing_write_bits); +int pld_connect_spi_to_jtag(struct pld_device *pld_device); +int pld_disconnect_spi_from_jtag(struct pld_device *pld_device); + struct pld_driver { const char *name; __PLD_CREATE_COMMAND((*pld_create_command)); const struct command_registration *commands; int (*load)(struct pld_device *pld_device, const char *filename); int (*get_ipdbg_hub)(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub); + int (*has_jtagspi_instruction)(struct pld_device *device, bool *has_instruction); + int (*get_jtagspi_userircode)(struct pld_device *pld_device, unsigned int *ir); + int (*connect_spi_to_jtag)(struct pld_device *pld_device); + int (*disconnect_spi_from_jtag)(struct pld_device *pld_device); + int (*get_stuff_bits)(struct pld_device *pld_device, unsigned int *facing_read_bits, + unsigned int *trailing_write_bits); }; #define PLD_CREATE_COMMAND_HANDLER(name) \ diff --git a/tcl/cpld/jtagspi.cfg b/tcl/cpld/jtagspi.cfg index 4c84792fe1..a7f02b9770 100644 --- a/tcl/cpld/jtagspi.cfg +++ b/tcl/cpld/jtagspi.cfg @@ -4,6 +4,8 @@ set _USER1 0x02 if { [info exists JTAGSPI_IR] } { set _JTAGSPI_IR $JTAGSPI_IR +} elseif {[info exists JTAGSPI_CHAIN_ID]} { + set _JTAGSPI_CHAIN_ID $JTAGSPI_CHAIN_ID } else { set _JTAGSPI_IR $_USER1 } @@ -21,7 +23,11 @@ if { [info exists FLASHNAME] } { } target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap -flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME $_JTAGSPI_IR +if { [info exists _JTAGSPI_IR] } { + flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME $_JTAGSPI_IR +} else { + flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME -pld $_JTAGSPI_CHAIN_ID +} # initialize jtagspi flash # chain_id: identifier of pld (you can get a list with 'pld devices') @@ -33,7 +39,9 @@ flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME $_JTAGSPI_IR proc jtagspi_init {chain_id proxy_bit {release_from_pwr_down_cmd -1}} { # load proxy bitstream $proxy_bit and probe spi flash global _FLASHNAME - pld load $chain_id $proxy_bit + if { $proxy_bit ne "" } { + pld load $chain_id $proxy_bit + } reset halt if {$release_from_pwr_down_cmd != -1} { jtagspi cmd $_FLASHNAME 0 $release_from_pwr_down_cmd From 2b99846ab67dd53540a18ed43fc9394c94f940ff Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Fri, 24 Feb 2023 15:57:30 +0100 Subject: [PATCH 38/50] jtagspi/pld: add support from lattice ecp2/ecp3 driver Provide jtagspi with specific procedures to be able to use jtagspi for programming spi-flash devices on lattice ecp2 and ecp3 devices. Change-Id: I39028aba47a74a0479be16d52d318f4bff7f2ed4 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7823 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/pld/ecp2_3.c | 55 +++++++++++++++++++++++++++++++++++++++++ src/pld/ecp2_3.h | 3 +++ src/pld/lattice.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/src/pld/ecp2_3.c b/src/pld/ecp2_3.c index b1c2833d53..a7b7580c72 100644 --- a/src/pld/ecp2_3.c +++ b/src/pld/ecp2_3.c @@ -21,6 +21,7 @@ #define ISC_DISABLE 0x1E #define LSCC_READ_STATUS 0x53 #define LSCC_BITSTREAM_BURST 0x02 +#define PROGRAM_SPI 0x3A #define STATUS_DONE_BIT 0x00020000 #define STATUS_ERROR_BITS_ECP2 0x00040003 @@ -249,3 +250,57 @@ int lattice_ecp3_load(struct lattice_pld_device *lattice_device, struct lattice_ const uint32_t expected = STATUS_DONE_BIT; return lattice_verify_status_register_u32(lattice_device, out, expected, mask, false); } + +int lattice_ecp2_3_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info) +{ + if (!pld_device_info) + return ERROR_FAIL; + + struct jtag_tap *tap = pld_device_info->tap; + if (!tap) + return ERROR_FAIL; + + // erase configuration + int retval = lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + retval = lattice_set_instr(tap, ISC_ERASE, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + retval = lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + + // connect jtag to spi pins + retval = lattice_set_instr(tap, PROGRAM_SPI, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + + return jtag_execute_queue(); +} + +int lattice_ecp2_3_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info) +{ + if (!pld_device_info) + return ERROR_FAIL; + + struct jtag_tap *tap = pld_device_info->tap; + if (!tap) + return ERROR_FAIL; + + int retval = lattice_set_instr(tap, BYPASS, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + + return jtag_execute_queue(); +} + +int lattice_ecp2_3_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits) +{ + if (!pld_device_info) + return ERROR_FAIL; + + *facing_read_bits = 1; + + return ERROR_OK; +} diff --git a/src/pld/ecp2_3.h b/src/pld/ecp2_3.h index 5f3e9e97b3..c5dec5693a 100644 --- a/src/pld/ecp2_3.h +++ b/src/pld/ecp2_3.h @@ -15,5 +15,8 @@ int lattice_ecp2_3_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint3 int lattice_ecp2_3_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode); int lattice_ecp2_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file); int lattice_ecp3_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file); +int lattice_ecp2_3_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info); +int lattice_ecp2_3_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info); +int lattice_ecp2_3_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits); #endif /* OPENOCD_PLD_ECP2_3_H */ diff --git a/src/pld/lattice.c b/src/pld/lattice.c index 0cd08dd331..4085ec194e 100644 --- a/src/pld/lattice.c +++ b/src/pld/lattice.c @@ -342,6 +342,64 @@ static int lattice_get_ipdbg_hub(int user_num, struct pld_device *pld_device, st return ERROR_OK; } +static int lattice_connect_spi_to_jtag(struct pld_device *pld_device) +{ + if (!pld_device) + return ERROR_FAIL; + + struct lattice_pld_device *pld_device_info = pld_device->driver_priv; + + int retval = lattice_check_device_family(pld_device_info); + if (retval != ERROR_OK) + return retval; + + if (pld_device_info->family == LATTICE_ECP2 || pld_device_info->family == LATTICE_ECP3) + return lattice_ecp2_3_connect_spi_to_jtag(pld_device_info); + + return ERROR_FAIL; +} + +static int lattice_disconnect_spi_from_jtag(struct pld_device *pld_device) +{ + if (!pld_device) + return ERROR_FAIL; + + struct lattice_pld_device *pld_device_info = pld_device->driver_priv; + + int retval = lattice_check_device_family(pld_device_info); + if (retval != ERROR_OK) + return retval; + + if (pld_device_info->family == LATTICE_ECP2 || pld_device_info->family == LATTICE_ECP3) + return lattice_ecp2_3_disconnect_spi_from_jtag(pld_device_info); + + return ERROR_FAIL; +} + +static int lattice_get_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits, + unsigned int *trailing_write_bits) +{ + if (!pld_device) + return ERROR_FAIL; + + struct lattice_pld_device *pld_device_info = pld_device->driver_priv; + + int retval = lattice_check_device_family(pld_device_info); + if (retval != ERROR_OK) + return retval; + + if (pld_device_info->family == LATTICE_ECP2 || pld_device_info->family == LATTICE_ECP3) + return lattice_ecp2_3_get_facing_read_bits(pld_device_info, facing_read_bits); + + return ERROR_FAIL; +} + +static int lattice_has_jtagspi_instruction(struct pld_device *device, bool *has_instruction) +{ + *has_instruction = true; + return ERROR_OK; +} + PLD_CREATE_COMMAND_HANDLER(lattice_pld_create_command) { if (CMD_ARGC != 4 && CMD_ARGC != 6) @@ -551,4 +609,8 @@ struct pld_driver lattice_pld = { .pld_create_command = &lattice_pld_create_command, .load = &lattice_load_command, .get_ipdbg_hub = lattice_get_ipdbg_hub, + .has_jtagspi_instruction = lattice_has_jtagspi_instruction, + .connect_spi_to_jtag = lattice_connect_spi_to_jtag, + .disconnect_spi_from_jtag = lattice_disconnect_spi_from_jtag, + .get_stuff_bits = lattice_get_stuff_bits, }; From 536f2a9f2a7754d7975e2618bc19fcbc03e44f54 Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Sat, 17 Dec 2022 13:11:30 +0100 Subject: [PATCH 39/50] jtagspi/pld: add support from lattice ecp5 driver Provide jtagspi with specific procedures to be able to use jtagspi for programming spi-flash devices on lattice ecp5 devices. Change-Id: I4a4a60f21d7e8685a5b8320b9c6ebdc2693bbd21 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7824 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/pld/ecp5.c | 71 +++++++++++++++++++++++++++++++++++ src/pld/ecp5.h | 3 ++ src/pld/lattice.c | 6 +++ src/pld/lattice_cmd.h | 1 + tcl/board/ecp5_evaluation.cfg | 8 +++- 5 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/pld/ecp5.c b/src/pld/ecp5.c index 2e1009baa2..024fe2b4a7 100644 --- a/src/pld/ecp5.c +++ b/src/pld/ecp5.c @@ -205,3 +205,74 @@ int lattice_ecp5_load(struct lattice_pld_device *lattice_device, struct lattice_ const uint32_t mask3 = STATUS_DONE_BIT | STATUS_FAIL_FLAG; return lattice_verify_status_register_u32(lattice_device, out, expected2, mask3, false); } + +int lattice_ecp5_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info) +{ + if (!pld_device_info) + return ERROR_FAIL; + + struct jtag_tap *tap = pld_device_info->tap; + if (!tap) + return ERROR_FAIL; + + if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == PROGRAM_SPI) + return ERROR_OK; + + // erase configuration + int retval = lattice_preload(pld_device_info); + if (retval != ERROR_OK) + return retval; + + retval = lattice_ecp5_enable_sram_programming(tap); + if (retval != ERROR_OK) + return retval; + + retval = lattice_ecp5_erase_sram(tap); + if (retval != ERROR_OK) + return retval; + + retval = lattice_ecp5_exit_programming_mode(tap); + if (retval != ERROR_OK) + return retval; + + // connect jtag to spi pins + retval = lattice_set_instr(tap, PROGRAM_SPI, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + + struct scan_field field; + uint8_t buffer[2] = {0xfe, 0x68}; + field.num_bits = 16; + field.out_value = buffer; + field.in_value = NULL; + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); + + return jtag_execute_queue(); +} + +int lattice_ecp5_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info) +{ + if (!pld_device_info) + return ERROR_FAIL; + + struct jtag_tap *tap = pld_device_info->tap; + if (!tap) + return ERROR_FAIL; + + /* Connecting it again takes way too long to do it multiple times for writing + a bitstream (ca. 0.4s each access). + We just leave it connected since SCS will not be active when not in shift_dr state. + So there is no need to change instruction, just make sure we are not in shift dr state. */ + jtag_add_runtest(2, TAP_IDLE); + return jtag_execute_queue(); +} + +int lattice_ecp5_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits) +{ + if (!pld_device_info) + return ERROR_FAIL; + + *facing_read_bits = 0; + + return ERROR_OK; +} diff --git a/src/pld/ecp5.h b/src/pld/ecp5.h index 7b0c86b4ad..daf481fa6a 100644 --- a/src/pld/ecp5.h +++ b/src/pld/ecp5.h @@ -14,5 +14,8 @@ int lattice_ecp5_read_status(struct jtag_tap *tap, uint32_t *status, uint32_t ou int lattice_ecp5_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out); int lattice_ecp5_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode); int lattice_ecp5_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file); +int lattice_ecp5_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info); +int lattice_ecp5_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info); +int lattice_ecp5_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits); #endif /* OPENOCD_PLD_ECP5_H */ diff --git a/src/pld/lattice.c b/src/pld/lattice.c index 4085ec194e..14dbf2ae71 100644 --- a/src/pld/lattice.c +++ b/src/pld/lattice.c @@ -355,6 +355,8 @@ static int lattice_connect_spi_to_jtag(struct pld_device *pld_device) if (pld_device_info->family == LATTICE_ECP2 || pld_device_info->family == LATTICE_ECP3) return lattice_ecp2_3_connect_spi_to_jtag(pld_device_info); + else if (pld_device_info->family == LATTICE_ECP5) + return lattice_ecp5_connect_spi_to_jtag(pld_device_info); return ERROR_FAIL; } @@ -372,6 +374,8 @@ static int lattice_disconnect_spi_from_jtag(struct pld_device *pld_device) if (pld_device_info->family == LATTICE_ECP2 || pld_device_info->family == LATTICE_ECP3) return lattice_ecp2_3_disconnect_spi_from_jtag(pld_device_info); + else if (pld_device_info->family == LATTICE_ECP5) + return lattice_ecp5_disconnect_spi_from_jtag(pld_device_info); return ERROR_FAIL; } @@ -390,6 +394,8 @@ static int lattice_get_stuff_bits(struct pld_device *pld_device, unsigned int *f if (pld_device_info->family == LATTICE_ECP2 || pld_device_info->family == LATTICE_ECP3) return lattice_ecp2_3_get_facing_read_bits(pld_device_info, facing_read_bits); + else if (pld_device_info->family == LATTICE_ECP5) + return lattice_ecp5_get_facing_read_bits(pld_device_info, facing_read_bits); return ERROR_FAIL; } diff --git a/src/pld/lattice_cmd.h b/src/pld/lattice_cmd.h index 8d66ac4c4e..389b7afe42 100644 --- a/src/pld/lattice_cmd.h +++ b/src/pld/lattice_cmd.h @@ -10,6 +10,7 @@ #define ISC_ERASE 0x0E #define ISC_DISABLE 0x26 +#define PROGRAM_SPI 0x3A #define LSC_READ_STATUS 0x3C #define LSC_INIT_ADDRESS 0x46 #define LSC_BITSTREAM_BURST 0x7A diff --git a/tcl/board/ecp5_evaluation.cfg b/tcl/board/ecp5_evaluation.cfg index 427037b71f..dd663f79d8 100644 --- a/tcl/board/ecp5_evaluation.cfg +++ b/tcl/board/ecp5_evaluation.cfg @@ -15,5 +15,11 @@ adapter speed 6000 source [find fpga/lattice_ecp5.cfg] -#openocd -f board/ecp5_evaluation.cfg -c "init" -c "pld load 0 shared_folder/ecp5_blinker_impl1.bit" +#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 + +set JTAGSPI_CHAIN_ID ecp5.pld +source [find cpld/jtagspi.cfg] + +#jtagspi_init ecp5.pld "" -1 +#jtagspi_program shared_folder/ecp5_blinker_impl1_slow.bit 0 From 302027094bfa9f331f5de2d25ecea01bac68a58a Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Sat, 17 Dec 2022 13:11:30 +0100 Subject: [PATCH 40/50] jtagspi/pld: add support from lattice certus driver Provide jtagspi with specific procedures to be able to use jtagspi for programming spi-flash devices on lattice certus and certus po devices. Change-Id: I6a8ec16be78f86073a4ef5302f6241185b08e1c6 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7825 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/pld/certus.c | 73 ++++++++++++++++++++++++++++++ src/pld/certus.h | 3 ++ src/pld/lattice.c | 6 +++ tcl/board/certuspro_evaluation.cfg | 8 ++++ 4 files changed, 90 insertions(+) diff --git a/src/pld/certus.c b/src/pld/certus.c index 1309c1b27d..8bfdff4952 100644 --- a/src/pld/certus.c +++ b/src/pld/certus.c @@ -231,3 +231,76 @@ int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattic return lattice_certus_exit_programming_mode(tap); } + +int lattice_certus_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info) +{ + if (!pld_device_info) + return ERROR_FAIL; + + struct jtag_tap *tap = pld_device_info->tap; + if (!tap) + return ERROR_FAIL; + + if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == PROGRAM_SPI) + return ERROR_OK; + + // erase configuration + int retval = lattice_preload(pld_device_info); + if (retval != ERROR_OK) + return retval; + + retval = lattice_certus_enable_programming(tap); + if (retval != ERROR_OK) + return retval; + + retval = lattice_certus_erase_device(pld_device_info); + if (retval != ERROR_OK) { + LOG_ERROR("erasing device failed"); + return retval; + } + + retval = lattice_certus_exit_programming_mode(tap); + if (retval != ERROR_OK) + return retval; + + // connect jtag to spi pins + retval = lattice_set_instr(tap, PROGRAM_SPI, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + + struct scan_field field; + uint8_t buffer[2] = {0xfe, 0x68}; + field.num_bits = 16; + field.out_value = buffer; + field.in_value = NULL; + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); + + return jtag_execute_queue(); +} + +int lattice_certus_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info) +{ + if (!pld_device_info) + return ERROR_FAIL; + + struct jtag_tap *tap = pld_device_info->tap; + if (!tap) + return ERROR_FAIL; + + /* Connecting it again takes way too long to do it multiple times for writing + a bitstream (ca. 0.4s each access). + We just leave it connected since SCS will not be active when not in shift_dr state. + So there is no need to change instruction, just make sure we are not in shift dr state. */ + jtag_add_runtest(2, TAP_IDLE); + return jtag_execute_queue(); +} + +int lattice_certus_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits) +{ + if (!pld_device_info) + return ERROR_FAIL; + + *facing_read_bits = 0; + + return ERROR_OK; +} diff --git a/src/pld/certus.h b/src/pld/certus.h index 51defc5ca2..d21ad61d20 100644 --- a/src/pld/certus.h +++ b/src/pld/certus.h @@ -14,5 +14,8 @@ int lattice_certus_read_status(struct jtag_tap *tap, uint64_t *status, uint64_t int lattice_certus_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out); int lattice_certus_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode); int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file); +int lattice_certus_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info); +int lattice_certus_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info); +int lattice_certus_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits); #endif /* OPENOCD_PLD_CERTUS_H */ diff --git a/src/pld/lattice.c b/src/pld/lattice.c index 14dbf2ae71..4858603a86 100644 --- a/src/pld/lattice.c +++ b/src/pld/lattice.c @@ -357,6 +357,8 @@ static int lattice_connect_spi_to_jtag(struct pld_device *pld_device) return lattice_ecp2_3_connect_spi_to_jtag(pld_device_info); else if (pld_device_info->family == LATTICE_ECP5) return lattice_ecp5_connect_spi_to_jtag(pld_device_info); + else if (pld_device_info->family == LATTICE_CERTUS) + return lattice_certus_connect_spi_to_jtag(pld_device_info); return ERROR_FAIL; } @@ -376,6 +378,8 @@ static int lattice_disconnect_spi_from_jtag(struct pld_device *pld_device) return lattice_ecp2_3_disconnect_spi_from_jtag(pld_device_info); else if (pld_device_info->family == LATTICE_ECP5) return lattice_ecp5_disconnect_spi_from_jtag(pld_device_info); + else if (pld_device_info->family == LATTICE_CERTUS) + return lattice_certus_disconnect_spi_from_jtag(pld_device_info); return ERROR_FAIL; } @@ -396,6 +400,8 @@ static int lattice_get_stuff_bits(struct pld_device *pld_device, unsigned int *f return lattice_ecp2_3_get_facing_read_bits(pld_device_info, facing_read_bits); else if (pld_device_info->family == LATTICE_ECP5) return lattice_ecp5_get_facing_read_bits(pld_device_info, facing_read_bits); + else if (pld_device_info->family == LATTICE_CERTUS) + return lattice_certus_get_facing_read_bits(pld_device_info, facing_read_bits); return ERROR_FAIL; } diff --git a/tcl/board/certuspro_evaluation.cfg b/tcl/board/certuspro_evaluation.cfg index 5ff2a1e329..ba2f17c221 100644 --- a/tcl/board/certuspro_evaluation.cfg +++ b/tcl/board/certuspro_evaluation.cfg @@ -12,3 +12,11 @@ transport select jtag adapter speed 10000 source [find fpga/lattice_certuspro.cfg] + +#openocd -f board/certuspro_evaluation.cfg -c "init" -c "pld load certuspro.pld shared_folder/certuspro_blinker_impl_1.bit" + +set JTAGSPI_CHAIN_ID certuspro.pld +source [find cpld/jtagspi.cfg] + +#jtagspi_init certuspro.pld "" -1 +#jtagspi_program shared_folder/certuspro_blinker_impl1.bit 0 From b2a22943e1d76b549c5ff5e84b95658abbd89a69 Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Sat, 17 Dec 2022 13:11:30 +0100 Subject: [PATCH 41/50] jtagspi/pld: add support from efinix driver Provide jtagspi with information to use jtagspi for programming spi-flash devices on efinix trion and titanium devices using a proxy bitstream. Change-Id: I4a851fcaafe832c35bd7b825d95a3d08e4d57a7b Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7826 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/pld/efinix.c | 7 +++++++ tcl/board/trion_t20_bga256.cfg | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/pld/efinix.c b/src/pld/efinix.c index 8350cb1a24..b6e5f9e477 100644 --- a/src/pld/efinix.c +++ b/src/pld/efinix.c @@ -249,6 +249,12 @@ static int efinix_get_ipdbg_hub(int user_num, struct pld_device *pld_device, str return ERROR_OK; } +static int efinix_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir) +{ + *ir = USER1; + return ERROR_OK; +} + PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command) { if (CMD_ARGC != 4 && CMD_ARGC != 6) @@ -296,4 +302,5 @@ struct pld_driver efinix_pld = { .pld_create_command = &efinix_pld_create_command, .load = &efinix_load, .get_ipdbg_hub = efinix_get_ipdbg_hub, + .get_jtagspi_userircode = efinix_get_jtagspi_userircode, }; diff --git a/tcl/board/trion_t20_bga256.cfg b/tcl/board/trion_t20_bga256.cfg index 045d63de33..dc76d39104 100644 --- a/tcl/board/trion_t20_bga256.cfg +++ b/tcl/board/trion_t20_bga256.cfg @@ -19,6 +19,11 @@ adapter speed 6000 source [find fpga/efinix_trion.cfg] -#openocd -f board/trion_t20_bga256.cfg -c "init" -c "pld load 0 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 +set JTAGSPI_CHAIN_ID trion.pld +source [find cpld/jtagspi.cfg] + +#jtagspi_init trion.pld "trion_jtagspi/outflow/trion_jtagspi.bit" 0xAB +#jtagspi_program trion_blinker/outflow/trion_blinker.bin 0 From 2d4fd58fca2afe32138ea66afbc458471c67046a Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Sat, 17 Dec 2022 13:11:30 +0100 Subject: [PATCH 42/50] jtagspi/pld: add support from xilinx driver Provide jtagspi with information to use jtagspi for programming spi-flash devices on xilinx devices using a proxy bitstream. Change-Id: I68000d71de25118ed8a8603e544cff1dc69bd9ba Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7836 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/pld/virtex2.c | 16 ++++++++++++++++ tcl/board/digilent_cmod_s7.cfg | 25 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tcl/board/digilent_cmod_s7.cfg diff --git a/src/pld/virtex2.c b/src/pld/virtex2.c index 9b4a0979f3..fce764c1af 100644 --- a/src/pld/virtex2.c +++ b/src/pld/virtex2.c @@ -326,6 +326,21 @@ static int xilinx_get_ipdbg_hub(int user_num, struct pld_device *pld_device, str return ERROR_OK; } +static int xilinx_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir) +{ + if (!pld_device || !pld_device->driver_priv) + return ERROR_FAIL; + struct virtex2_pld_device *pld_device_info = pld_device->driver_priv; + + if (pld_device_info->command_set.num_user < 1) { + LOG_ERROR("code for command 'select user1' is unknown"); + return ERROR_FAIL; + } + + *ir = pld_device_info->command_set.user[0]; + return ERROR_OK; +} + COMMAND_HANDLER(virtex2_handle_set_instuction_codes_command) { if (CMD_ARGC < 6 || CMD_ARGC > (6 + VIRTEX2_MAX_USER_INSTRUCTIONS)) @@ -460,4 +475,5 @@ struct pld_driver virtex2_pld = { .pld_create_command = &virtex2_pld_create_command, .load = &virtex2_load, .get_ipdbg_hub = xilinx_get_ipdbg_hub, + .get_jtagspi_userircode = xilinx_get_jtagspi_userircode, }; diff --git a/tcl/board/digilent_cmod_s7.cfg b/tcl/board/digilent_cmod_s7.cfg new file mode 100644 index 0000000000..c52ee9505b --- /dev/null +++ b/tcl/board/digilent_cmod_s7.cfg @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# digilent CMOD S7 +# https://digilent.com/reference/programmable-logic/cmod-s7/reference-manual + + +adapter driver ftdi +ftdi channel 0 +ftdi layout_init 0x0008 0x008b +ftdi vid_pid 0x0403 0x6010 +reset_config none +transport select jtag + +adapter speed 10000 + +source [find cpld/xilinx-xc7.cfg] + +# "ipdbg -start -tap xc7.tap -hub 0x02 -tool 0 -port 5555" +#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 +source [find cpld/jtagspi.cfg] + +#jtagspi_init xc7.pld "shared_folder/bscan_spi_xc7s25.bit" 0xab +#jtagspi_program shared_folder/cmod_s7_fast.bit 0 From b86726b5a5bb1d2689a786b3294e8617867d5ef4 Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Sat, 17 Dec 2022 13:11:30 +0100 Subject: [PATCH 43/50] jtagspi/pld: add support from intel driver Provide jtagspi with information to use jtagspi for programming spi-flash devices on intel devices using a proxy bitstream. Change-Id: Ib947b8c0dd61e2c6fa8beeb30074606131b1480f Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7837 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/pld/intel.c | 8 +++++++- tcl/board/bemicro_cycloneiii.cfg | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/pld/intel.c b/src/pld/intel.c index ee3097391b..8422c94c4b 100644 --- a/src/pld/intel.c +++ b/src/pld/intel.c @@ -362,6 +362,12 @@ static int intel_get_ipdbg_hub(int user_num, struct pld_device *pld_device, stru return ERROR_OK; } +static int intel_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir) +{ + *ir = USER1; + return ERROR_OK; +} + COMMAND_HANDLER(intel_set_bscan_command_handler) { unsigned int boundary_scan_length; @@ -412,7 +418,6 @@ COMMAND_HANDLER(intel_set_check_pos_command_handler) return ERROR_OK; } - PLD_CREATE_COMMAND_HANDLER(intel_pld_create_command) { if (CMD_ARGC != 4 && CMD_ARGC != 6) @@ -498,4 +503,5 @@ struct pld_driver intel_pld = { .pld_create_command = &intel_pld_create_command, .load = &intel_load, .get_ipdbg_hub = intel_get_ipdbg_hub, + .get_jtagspi_userircode = intel_get_jtagspi_userircode, }; diff --git a/tcl/board/bemicro_cycloneiii.cfg b/tcl/board/bemicro_cycloneiii.cfg index 95dd394fd4..bd1459adc4 100644 --- a/tcl/board/bemicro_cycloneiii.cfg +++ b/tcl/board/bemicro_cycloneiii.cfg @@ -16,5 +16,9 @@ source [find fpga/altera-cycloneiii.cfg] #quartus_cpf --option=bitstream_compression=off -c output_files\cycloneiii_blinker.sof cycloneiii_blinker.rbf -#openocd -f board/bemicro_cycloneiii.cfg -c "init" -c "pld load 0 cycloneiii_blinker.rbf" +#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" + + +set JTAGSPI_CHAIN_ID cycloneiii.pld +source [find cpld/jtagspi.cfg] From 198a914cf99a8602a05227ac5327a805714e4b87 Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Sat, 17 Dec 2022 13:11:30 +0100 Subject: [PATCH 44/50] jtagspi/pld: add support from gatemate driver Provide jtagspi with specific procedures to be able to use jtagspi for programming spi-flash devices on cologne chip gatemate devices. Change-Id: Ifa1c4ca6e215d7f49bd21620898991af213812e9 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7838 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/pld/gatemate.c | 66 +++++++++++++++++++++++++++++++++++++ tcl/board/gatemate_eval.cfg | 6 ++++ 2 files changed, 72 insertions(+) diff --git a/src/pld/gatemate.c b/src/pld/gatemate.c index 4ad2665c6a..f35b39ad21 100644 --- a/src/pld/gatemate.c +++ b/src/pld/gatemate.c @@ -15,6 +15,8 @@ #include "raw_bit.h" #define JTAG_CONFIGURE 0x06 +#define JTAG_SPI_BYPASS 0x05 +#define BYPASS 0x3F struct gatemate_pld_device { struct jtag_tap *tap; @@ -209,6 +211,66 @@ static int gatemate_load(struct pld_device *pld_device, const char *filename) return retval; } +static int gatemate_has_jtagspi_instruction(struct pld_device *device, bool *has_instruction) +{ + *has_instruction = true; + return ERROR_OK; +} + +static int gatemate_connect_spi_to_jtag(struct pld_device *pld_device) +{ + if (!pld_device) + return ERROR_FAIL; + + struct gatemate_pld_device *pld_device_info = pld_device->driver_priv; + if (!pld_device_info) + return ERROR_FAIL; + + struct jtag_tap *tap = pld_device_info->tap; + if (!tap) + return ERROR_FAIL; + + if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == JTAG_SPI_BYPASS) + return ERROR_OK; + + gatemate_set_instr(tap, JTAG_SPI_BYPASS); + + return jtag_execute_queue(); +} + +static int gatemate_disconnect_spi_from_jtag(struct pld_device *pld_device) +{ + if (!pld_device) + return ERROR_FAIL; + + struct gatemate_pld_device *pld_device_info = pld_device->driver_priv; + if (!pld_device_info) + return ERROR_FAIL; + + struct jtag_tap *tap = pld_device_info->tap; + if (!tap) + return ERROR_FAIL; + + if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != JTAG_SPI_BYPASS) + return ERROR_OK; + + gatemate_set_instr(tap, BYPASS); + + return jtag_execute_queue(); +} + +static int gatemate_get_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits, + unsigned int *trailing_write_bits) +{ + if (!pld_device) + return ERROR_FAIL; + + *facing_read_bits = 1; + *trailing_write_bits = 1; + + return ERROR_OK; +} + PLD_CREATE_COMMAND_HANDLER(gatemate_pld_create_command) { if (CMD_ARGC != 4) @@ -239,4 +301,8 @@ struct pld_driver gatemate_pld = { .name = "gatemate", .pld_create_command = &gatemate_pld_create_command, .load = &gatemate_load, + .has_jtagspi_instruction = gatemate_has_jtagspi_instruction, + .connect_spi_to_jtag = gatemate_connect_spi_to_jtag, + .disconnect_spi_from_jtag = gatemate_disconnect_spi_from_jtag, + .get_stuff_bits = gatemate_get_stuff_bits, }; diff --git a/tcl/board/gatemate_eval.cfg b/tcl/board/gatemate_eval.cfg index cc078a0e30..c4d3f3dfda 100644 --- a/tcl/board/gatemate_eval.cfg +++ b/tcl/board/gatemate_eval.cfg @@ -14,3 +14,9 @@ transport select jtag adapter speed 6000 source [find fpga/gatemate.cfg] + +set JTAGSPI_CHAIN_ID gatemate.pld +source [find cpld/jtagspi.cfg] + +#jtagspi_init gatemate.pld "" -1 +#jtagspi_program workspace/blink/blink_slow.cfg.bit 0 From eb22a37b42a7944694243b690bfbd736e1ef52e8 Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Sat, 17 Dec 2022 13:11:30 +0100 Subject: [PATCH 45/50] pld: harmonize refresh commands add refresh command for lattice devices rename gowin reprogram to refresh rename virtex2 program to refresh Change-Id: I9da83a614b96da3e947ac4608b0a291b1d126914 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7839 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 12 ++++++++---- src/pld/certus.c | 24 ++++++++++++++++++++++++ src/pld/certus.h | 1 + src/pld/ecp2_3.c | 11 +++++++++++ src/pld/ecp2_3.h | 1 + src/pld/ecp5.c | 24 ++++++++++++++++++++++++ src/pld/ecp5.h | 1 + src/pld/gowin.c | 4 ++-- src/pld/lattice.c | 35 +++++++++++++++++++++++++++++++++++ src/pld/lattice_cmd.h | 1 + src/pld/virtex2.c | 8 ++++---- 11 files changed, 112 insertions(+), 10 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 7ad48c8629..2d59238b80 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -8764,8 +8764,8 @@ Change values for boundary scan instructions selecting the registers USER1 to US Description of the arguments can be found at command @command{virtex2 set_instr_codes}. @end deffn -@deffn {Command} {virtex2 program} pld_name -Load the bitstream from external memory for FPGA @var{pld_name}. A.k.a. refresh. +@deffn {Command} {virtex2 refresh} pld_name +Load the bitstream from external memory for FPGA @var{pld_name}. A.k.a. program. @end deffn @end deffn @@ -8796,6 +8796,10 @@ for FPGA @var{pld_name} with value @var{val}. Set the length of the register for the preload. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices). The load command for the FPGA @var{pld_name} will use a length for the preload of @var{length}. @end deffn + +@deffn {Command} {lattice refresh} pld_name +Load the bitstream from external memory for FPGA @var{pld_name}. A.k.a program. +@end deffn @end deffn @@ -8850,9 +8854,9 @@ Reads and displays the user register for FPGA @var{pld_name}. @end deffn -@deffn {Command} {gowin reload} pld_name +@deffn {Command} {gowin refresh} pld_name Load the bitstream from external memory for -FPGA @var{pld_name}. A.k.a. refresh. +FPGA @var{pld_name}. A.k.a. reload. @end deffn @end deffn diff --git a/src/pld/certus.c b/src/pld/certus.c index 8bfdff4952..a49501f541 100644 --- a/src/pld/certus.c +++ b/src/pld/certus.c @@ -304,3 +304,27 @@ int lattice_certus_get_facing_read_bits(struct lattice_pld_device *pld_device_in return ERROR_OK; } + +int lattice_certus_refresh(struct lattice_pld_device *lattice_device) +{ + struct jtag_tap *tap = lattice_device->tap; + if (!tap) + return ERROR_FAIL; + + int retval = lattice_preload(lattice_device); + if (retval != ERROR_OK) + return retval; + + retval = lattice_set_instr(tap, LSC_REFRESH, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + jtag_add_runtest(2, TAP_IDLE); + jtag_add_sleep(200000); + retval = lattice_set_instr(tap, BYPASS, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + jtag_add_runtest(100, TAP_IDLE); + jtag_add_sleep(1000); + + return jtag_execute_queue(); +} diff --git a/src/pld/certus.h b/src/pld/certus.h index d21ad61d20..0fbfdef45c 100644 --- a/src/pld/certus.h +++ b/src/pld/certus.h @@ -17,5 +17,6 @@ int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattic int lattice_certus_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info); int lattice_certus_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info); int lattice_certus_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits); +int lattice_certus_refresh(struct lattice_pld_device *lattice_device); #endif /* OPENOCD_PLD_CERTUS_H */ diff --git a/src/pld/ecp2_3.c b/src/pld/ecp2_3.c index a7b7580c72..5dfea9a277 100644 --- a/src/pld/ecp2_3.c +++ b/src/pld/ecp2_3.c @@ -304,3 +304,14 @@ int lattice_ecp2_3_get_facing_read_bits(struct lattice_pld_device *pld_device_in return ERROR_OK; } + +int lattice_ecp2_3_refresh(struct lattice_pld_device *lattice_device) +{ + if (!lattice_device || !lattice_device->tap) + return ERROR_FAIL; + + int retval = lattice_set_instr(lattice_device->tap, LSCC_REFRESH, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + return jtag_execute_queue(); +} diff --git a/src/pld/ecp2_3.h b/src/pld/ecp2_3.h index c5dec5693a..d3f7464e12 100644 --- a/src/pld/ecp2_3.h +++ b/src/pld/ecp2_3.h @@ -18,5 +18,6 @@ int lattice_ecp3_load(struct lattice_pld_device *lattice_device, struct lattice_ int lattice_ecp2_3_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info); int lattice_ecp2_3_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info); int lattice_ecp2_3_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits); +int lattice_ecp2_3_refresh(struct lattice_pld_device *lattice_device); #endif /* OPENOCD_PLD_ECP2_3_H */ diff --git a/src/pld/ecp5.c b/src/pld/ecp5.c index 024fe2b4a7..f8ba33eaff 100644 --- a/src/pld/ecp5.c +++ b/src/pld/ecp5.c @@ -276,3 +276,27 @@ int lattice_ecp5_get_facing_read_bits(struct lattice_pld_device *pld_device_info return ERROR_OK; } + +int lattice_ecp5_refresh(struct lattice_pld_device *lattice_device) +{ + struct jtag_tap *tap = lattice_device->tap; + if (!tap) + return ERROR_FAIL; + + int retval = lattice_preload(lattice_device); + if (retval != ERROR_OK) + return retval; + + retval = lattice_set_instr(tap, LSC_REFRESH, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + jtag_add_runtest(2, TAP_IDLE); + jtag_add_sleep(200000); + retval = lattice_set_instr(tap, BYPASS, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + jtag_add_runtest(100, TAP_IDLE); + jtag_add_sleep(1000); + + return jtag_execute_queue(); +} diff --git a/src/pld/ecp5.h b/src/pld/ecp5.h index daf481fa6a..975678ece3 100644 --- a/src/pld/ecp5.h +++ b/src/pld/ecp5.h @@ -17,5 +17,6 @@ int lattice_ecp5_load(struct lattice_pld_device *lattice_device, struct lattice_ int lattice_ecp5_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info); int lattice_ecp5_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info); int lattice_ecp5_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits); +int lattice_ecp5_refresh(struct lattice_pld_device *lattice_device); #endif /* OPENOCD_PLD_ECP5_H */ diff --git a/src/pld/gowin.c b/src/pld/gowin.c index c42b2f22c9..bbc2fe15f6 100644 --- a/src/pld/gowin.c +++ b/src/pld/gowin.c @@ -543,10 +543,10 @@ static const struct command_registration gowin_exec_command_handlers[] = { .help = "reading user register from FPGA", .usage = "pld_name", }, { - .name = "reload", + .name = "refresh", .mode = COMMAND_EXEC, .handler = gowin_reload_command_handler, - .help = "reloading bitstream from flash to SRAM", + .help = "reload bitstream from flash to SRAM", .usage = "pld_name", }, COMMAND_REGISTRATION_DONE diff --git a/src/pld/lattice.c b/src/pld/lattice.c index 4858603a86..cd72d3cb59 100644 --- a/src/pld/lattice.c +++ b/src/pld/lattice.c @@ -575,6 +575,35 @@ COMMAND_HANDLER(lattice_read_status_command_handler) return retval; } +COMMAND_HANDLER(lattice_refresh_command_handler) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]); + if (!device) { + command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]); + return ERROR_FAIL; + } + + struct lattice_pld_device *lattice_device = device->driver_priv; + if (!lattice_device) + return ERROR_FAIL; + + int retval = lattice_check_device_family(lattice_device); + if (retval != ERROR_OK) + return retval; + + if (lattice_device->family == LATTICE_ECP2 || lattice_device->family == LATTICE_ECP3) + return lattice_ecp2_3_refresh(lattice_device); + else if (lattice_device->family == LATTICE_ECP5) + return lattice_ecp5_refresh(lattice_device); + else if (lattice_device->family == LATTICE_CERTUS) + return lattice_certus_refresh(lattice_device); + + return ERROR_FAIL; +} + static const struct command_registration lattice_exec_command_handlers[] = { { .name = "read_status", @@ -600,6 +629,12 @@ static const struct command_registration lattice_exec_command_handlers[] = { .handler = lattice_set_preload_command_handler, .help = "set length for preload (device specific)", .usage = "pld_name value", + }, { + .name = "refresh", + .mode = COMMAND_EXEC, + .handler = lattice_refresh_command_handler, + .help = "refresh from configuration memory", + .usage = "pld_name", }, COMMAND_REGISTRATION_DONE }; diff --git a/src/pld/lattice_cmd.h b/src/pld/lattice_cmd.h index 389b7afe42..0c10625832 100644 --- a/src/pld/lattice_cmd.h +++ b/src/pld/lattice_cmd.h @@ -13,6 +13,7 @@ #define PROGRAM_SPI 0x3A #define LSC_READ_STATUS 0x3C #define LSC_INIT_ADDRESS 0x46 +#define LSC_REFRESH 0x79 #define LSC_BITSTREAM_BURST 0x7A #define READ_USERCODE 0xC0 #define ISC_ENABLE 0xC6 diff --git a/src/pld/virtex2.c b/src/pld/virtex2.c index fce764c1af..3dff90621a 100644 --- a/src/pld/virtex2.c +++ b/src/pld/virtex2.c @@ -265,7 +265,7 @@ static int virtex2_load(struct pld_device *pld_device, const char *filename) return retval; } -COMMAND_HANDLER(virtex2_handle_program_command) +COMMAND_HANDLER(virtex2_handle_refresh_command) { struct pld_device *device; @@ -449,10 +449,10 @@ static const struct command_registration virtex2_exec_command_handlers[] = { .help = "set instructions codes used for jtag-hub", .usage = "pld_name user1 [user2 [user3 [user4]]]", }, { - .name = "program", + .name = "refresh", .mode = COMMAND_EXEC, - .handler = virtex2_handle_program_command, - .help = "start loading of configuration (refresh)", + .handler = virtex2_handle_refresh_command, + .help = "start loading of configuration (program)", .usage = "pld_name", }, COMMAND_REGISTRATION_DONE From f49bf1adb42e3ae1b63da5d6e615c6f28b49f42a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 14 Mar 2023 13:30:49 +0100 Subject: [PATCH 46/50] target/arm_adi_v5,jtag/drivers: rename ADIv5 only defines DP_SELECT_APSEL and DP_SELECT_APBANK is no more used in ADIv6. Change-Id: I4176574d46c6dc8eb3fe3aef6daab6e33492c050 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7538 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/rshim.c | 4 ++-- src/jtag/drivers/vdebug.c | 12 ++++++------ src/target/adi_v5_swd.c | 2 +- src/target/arm_adi_v5.h | 16 ++++++++-------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/jtag/drivers/rshim.c b/src/jtag/drivers/rshim.c index 174fa12752..6170e86bdb 100644 --- a/src/jtag/drivers/rshim.c +++ b/src/jtag/drivers/rshim.c @@ -254,8 +254,8 @@ static int rshim_dp_q_write(struct adiv5_dap *dap, unsigned int reg, dp_ctrl_stat = data; break; case DP_SELECT: - ap_sel = (data & DP_SELECT_APSEL) >> 24; - ap_bank = (data & DP_SELECT_APBANK) >> 4; + ap_sel = (data & ADIV5_DP_SELECT_APSEL) >> 24; + ap_bank = (data & ADIV5_DP_SELECT_APBANK) >> 4; break; default: LOG_INFO("Unknown command"); diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index f6d99c6c1c..d2311b2ea8 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -1098,9 +1098,9 @@ static int vdebug_dap_queue_dp_write(struct adiv5_dap *dap, unsigned int reg, ui static int vdebug_dap_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) { - if ((reg & DP_SELECT_APBANK) != ap->dap->select) { - vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & DP_SELECT_APBANK, VD_ASPACE_DP, 0); - ap->dap->select = reg & DP_SELECT_APBANK; + if ((reg & ADIV5_DP_SELECT_APBANK) != ap->dap->select) { + vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & ADIV5_DP_SELECT_APBANK, VD_ASPACE_DP, 0); + ap->dap->select = reg & ADIV5_DP_SELECT_APBANK; } vdebug_reg_read(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, NULL, VD_ASPACE_AP, 0); @@ -1110,9 +1110,9 @@ static int vdebug_dap_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint3 static int vdebug_dap_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) { - if ((reg & DP_SELECT_APBANK) != ap->dap->select) { - vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & DP_SELECT_APBANK, VD_ASPACE_DP, 0); - ap->dap->select = reg & DP_SELECT_APBANK; + if ((reg & ADIV5_DP_SELECT_APBANK) != ap->dap->select) { + vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & ADIV5_DP_SELECT_APBANK, VD_ASPACE_DP, 0); + ap->dap->select = reg & ADIV5_DP_SELECT_APBANK; } return vdebug_reg_write(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_AP, 0); diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 275a501286..5f40588d2f 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -147,7 +147,7 @@ static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg, swd_finish_read(dap); if (reg == DP_SELECT) { - dap->select = data & (DP_SELECT_APSEL | DP_SELECT_APBANK | DP_SELECT_DPBANK); + dap->select = data & (ADIV5_DP_SELECT_APSEL | ADIV5_DP_SELECT_APBANK | DP_SELECT_DPBANK); swd->write_reg(swd_cmd(false, false, reg), data, 0); diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 90d28bcf23..e21589363d 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -97,16 +97,16 @@ #define DP_DLPIDR_PROTVSN 1u -#define DP_SELECT_APSEL 0xFF000000 -#define DP_SELECT_APBANK 0x000000F0 -#define DP_SELECT_DPBANK 0x0000000F -#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */ +#define ADIV5_DP_SELECT_APSEL 0xFF000000 +#define ADIV5_DP_SELECT_APBANK 0x000000F0 +#define DP_SELECT_DPBANK 0x0000000F +#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */ -#define DP_APSEL_MAX (255) /* for ADIv5 only */ -#define DP_APSEL_INVALID 0xF00 /* more than DP_APSEL_MAX and not ADIv6 aligned 4k */ +#define DP_APSEL_MAX (255) /* Strict limit for ADIv5, number of AP buffers for ADIv6 */ +#define DP_APSEL_INVALID 0xF00 /* more than DP_APSEL_MAX and not ADIv6 aligned 4k */ -#define DP_TARGETSEL_INVALID 0xFFFFFFFFU -#define DP_TARGETSEL_DPID_MASK 0x0FFFFFFFU +#define DP_TARGETSEL_INVALID 0xFFFFFFFFU +#define DP_TARGETSEL_DPID_MASK 0x0FFFFFFFU #define DP_TARGETSEL_INSTANCEID_MASK 0xF0000000U #define DP_TARGETSEL_INSTANCEID_SHIFT 28 From 5fd4f2954d6673e5b2fd740da681439425794abc Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 14 Mar 2023 14:31:30 +0100 Subject: [PATCH 47/50] target/adi_v5_xxx: use ADIV5_DP_SELECT_APBANK and DP_SELECT_DPBANK. Use the defined symbols instead of magic numbers. Change-Id: I19c86b183e57e42b96f76eed180c0492cd67bee1 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7539 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/adi_v5_jtag.c | 4 ++-- src/target/adi_v5_swd.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index 9f66adc688..afdc0e5775 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -350,7 +350,7 @@ static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap, { uint8_t out_value_buf[4]; int retval; - uint64_t sel = (reg_addr >> 4) & 0xf; + uint64_t sel = (reg_addr >> 4) & DP_SELECT_DPBANK; /* No need to change SELECT or RDBUFF as they are not banked */ if (instr == JTAG_DP_DPACC && reg_addr != DP_SELECT && reg_addr != DP_RDBUFF && @@ -775,7 +775,7 @@ static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned reg) } /* ADIv5 */ - sel = (ap->ap_num << 24) | (reg & 0x000000F0); + sel = (ap->ap_num << 24) | (reg & ADIV5_DP_SELECT_APBANK); if (sel == dap->select) return ERROR_OK; diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 5f40588d2f..1b743657c2 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -523,7 +523,7 @@ static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg) } /* ADIv5 */ - sel = (ap->ap_num << 24) | (reg & 0x000000F0); + sel = (ap->ap_num << 24) | (reg & ADIV5_DP_SELECT_APBANK); if (dap->select != DP_SELECT_INVALID) sel |= dap->select & DP_SELECT_DPBANK; From eeee3f41daf2b4668a0c6f75bc621146caa84b77 Mon Sep 17 00:00:00 2001 From: Peter Mamonov Date: Fri, 26 Sep 2014 14:04:51 +0400 Subject: [PATCH 48/50] tcl/target: Add XLP3xx configuration files The patch adds configuration files for the following XLP 300-series processors: XLP304, XLP308, XLP316. Change-Id: Iaf2b807abf9fc4d7b51222fd40bdb18c6aca7d9c Signed-off-by: Aleksey Kuleshov Signed-off-by: Peter Mamonov CC: Antony Pavlov CC: Dongxue Zhang CC: Oleksij Rempel CC: Paul Fertser CC: Salvador Arroyo CC: Spencer Oliver Reviewed-on: https://review.openocd.org/c/openocd/+/2323 Tested-by: jenkins Reviewed-by: Oleksij Rempel Reviewed-by: Antonio Borneo --- tcl/target/netl_xlp304.cfg | 7 +++++++ tcl/target/netl_xlp308.cfg | 7 +++++++ tcl/target/netl_xlp316.cfg | 7 +++++++ tcl/target/netl_xlp3xx.cfg | 39 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 tcl/target/netl_xlp304.cfg create mode 100644 tcl/target/netl_xlp308.cfg create mode 100644 tcl/target/netl_xlp316.cfg create mode 100644 tcl/target/netl_xlp3xx.cfg diff --git a/tcl/target/netl_xlp304.cfg b/tcl/target/netl_xlp304.cfg new file mode 100644 index 0000000000..27c30a0d27 --- /dev/null +++ b/tcl/target/netl_xlp304.cfg @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Target: XLP304 processor by NetLogic Microsystems +# + +set XLP_NT 4 +source [find target/netl_xlp3xx.cfg] diff --git a/tcl/target/netl_xlp308.cfg b/tcl/target/netl_xlp308.cfg new file mode 100644 index 0000000000..c3ba11e781 --- /dev/null +++ b/tcl/target/netl_xlp308.cfg @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Target: XLP308 processor by NetLogic Microsystems +# + +set XLP_NT 8 +source [find target/netl_xlp3xx.cfg] diff --git a/tcl/target/netl_xlp316.cfg b/tcl/target/netl_xlp316.cfg new file mode 100644 index 0000000000..961b67f180 --- /dev/null +++ b/tcl/target/netl_xlp316.cfg @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Target: XLP316 processor by NetLogic Microsystems +# + +set XLP_NT 16 +source [find target/netl_xlp3xx.cfg] diff --git a/tcl/target/netl_xlp3xx.cfg b/tcl/target/netl_xlp3xx.cfg new file mode 100644 index 0000000000..2366503cb6 --- /dev/null +++ b/tcl/target/netl_xlp3xx.cfg @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Target: XLP 300-series processors by NetLogic Microsystems +# +# See http://www.broadcom.com/products/Processors/Enterprise/XLP300-Series +# +# Use xlp304.cfg, xlp308.cfg, xlp316.cfg for particular processor model. +# + +transport select jtag + +global XLP_NT + +for {set i $XLP_NT} {$i > 0} {incr i -1} { + jtag newtap xlp cpu_$i -irlen 5 -disable + if {$i != 1} { + jtag configure xlp.cpu_$i -event tap-enable {} + } +} +jtag newtap xlp jrc -irlen 16 -expected-id 0x00011449 + +jtag configure xlp.cpu_1 -event tap-enable { + global XLP_NT + irscan xlp.jrc 0xe0 + drscan xlp.jrc 1 1 + for {set i $XLP_NT} {$i > 1} {incr i -1} { + jtag tapenable xlp.cpu_$i + } +} + +proc chipreset {} { + irscan xlp.jrc 0xab + drscan xlp.jrc 1 1 + drscan xlp.jrc 1 0 +} + +jtag configure xlp.jrc -event setup "jtag tapenable xlp.cpu_1" + +target create xlp.cpu_1 mips_mips64 -endian big -chain-position xlp.cpu_1 From 4b1ea8511a7da9d7201df40302e3341c6e97ffdd Mon Sep 17 00:00:00 2001 From: Peter Mamonov Date: Wed, 26 Jun 2019 18:43:16 +0300 Subject: [PATCH 49/50] tcl/target: add support for Cavium Octeon II CN61xx Change-Id: Ia14854bc64f5a31b6591be69be4edee9cd1310c3 Signed-off-by: Peter Mamonov Reviewed-on: https://review.openocd.org/c/openocd/+/5249 Reviewed-by: Oleksij Rempel Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/cavium_cn61xx.cfg | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tcl/target/cavium_cn61xx.cfg diff --git a/tcl/target/cavium_cn61xx.cfg b/tcl/target/cavium_cn61xx.cfg new file mode 100644 index 0000000000..60b56a5192 --- /dev/null +++ b/tcl/target/cavium_cn61xx.cfg @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Cavium Octeon II CN61xx (PrID 0x000D9301) + +jtag newtap cpu tap0 -irlen 5 +jtag newtap cpu tap1 -irlen 5 + +target create cpu.core0 mips_mips64 -chain-position cpu.tap0 -endian big -rtos hwthread -coreid 0 +target create cpu.core1 mips_mips64 -chain-position cpu.tap1 -endian big -rtos hwthread -coreid 1 +target smp cpu.core0 cpu.core1 + +cpu.core0 configure -work-area-phys 0xffffffffa2000000 -work-area-size 0x20000 +cpu.core1 configure -work-area-phys 0xffffffffa2000000 -work-area-size 0x20000 + +targets cpu.core0 From c5185e9219ea596544c7d3edb889c3d7d353ff3f Mon Sep 17 00:00:00 2001 From: Kirill Radkin Date: Wed, 18 Oct 2023 19:13:25 +0300 Subject: [PATCH 50/50] breakpoints: Fix endless loop in bp/wp_clear_target If we can't remove bp/wp, we will stuck in endless loop Change-Id: I44c0a164db1d15c0a0637d33c75087a49cf5c0f4 Signed-off-by: Kirill Radkin Reviewed-on: https://review.openocd.org/c/openocd/+/7940 Tested-by: jenkins Reviewed-by: Anatoly P Reviewed-by: Tim Newsome Reviewed-by: Jan Matyas Reviewed-by: Antonio Borneo --- src/target/breakpoints.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 179404486e..44e7274b48 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -312,6 +312,8 @@ static int breakpoint_free(struct target *data_target, struct target *breakpoint static int breakpoint_remove_all_internal(struct target *target) { + LOG_TARGET_DEBUG(target, "Delete all breakpoints"); + struct breakpoint *breakpoint = target->breakpoints; int retval = ERROR_OK; @@ -436,22 +438,6 @@ int breakpoint_remove_all(struct target *target) return retval; } -static int breakpoint_clear_target_internal(struct target *target) -{ - LOG_DEBUG("Delete all breakpoints for target: %s", - target_name(target)); - - int retval = ERROR_OK; - - while (target->breakpoints) { - int status = breakpoint_free(target, target, target->breakpoints); - if (status != ERROR_OK) - retval = status; - } - - return retval; -} - int breakpoint_clear_target(struct target *target) { int retval = ERROR_OK; @@ -461,13 +447,13 @@ int breakpoint_clear_target(struct target *target) foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; - int status = breakpoint_clear_target_internal(curr); + int status = breakpoint_remove_all_internal(curr); if (status != ERROR_OK) retval = status; } } else { - retval = breakpoint_clear_target_internal(target); + retval = breakpoint_remove_all_internal(target); } return retval; @@ -663,16 +649,19 @@ int watchpoint_remove(struct target *target, target_addr_t address) int watchpoint_clear_target(struct target *target) { - int retval = ERROR_OK; - LOG_DEBUG("Delete all watchpoints for target: %s", target_name(target)); - while (target->watchpoints) { - int status = watchpoint_free(target, target->watchpoints); + + struct watchpoint *watchpoint = target->watchpoints; + int retval = ERROR_OK; + + while (watchpoint) { + struct watchpoint *tmp = watchpoint; + watchpoint = watchpoint->next; + int status = watchpoint_free(target, tmp); if (status != ERROR_OK) retval = status; } - return retval; }