From 0ace4b960e184269cd5dd31254a2e497ef7219b3 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 22 Jan 2024 16:33:54 +0000 Subject: [PATCH 01/27] icepick: Begun building support for the TI ICEPick controller --- src/target/icepick.c | 81 ++++++++++++++++++++++++++++++++++++++++++ src/target/icepick.h | 41 +++++++++++++++++++++ src/target/jtag_devs.c | 4 ++- src/target/meson.build | 22 ++++++++++-- 4 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 src/target/icepick.c create mode 100644 src/target/icepick.h diff --git a/src/target/icepick.c b/src/target/icepick.c new file mode 100644 index 00000000000..243640dce26 --- /dev/null +++ b/src/target/icepick.c @@ -0,0 +1,81 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2024 1BitSquared + * Written by Rachel Mant + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file implements support for the TI ICEPick controller that sits in front + * of TAPs in the scan chain on some TI devices. + * + * References: + * SPRUH35 - Using the ICEPick TAP (type-C) + * https://www.ti.com/lit/ug/spruh35/spruh35.pdf + */ + +#include "general.h" +#include "jtag_scan.h" +#include "jtagtap.h" +#include "icepick.h" + +#define IR_ROUTER 0x02U +#define IR_ICEPICKCODE 0x05U +#define IR_CONNECT 0x07U + +/* + * The type-C value is taken from SPRUH35, the type-D value is + * from a BeagleBone Black Industrial (AM3358BZCZA100) + */ +#define ICEPICK_TYPE_MASK 0xfff0U +#define ICEPICK_TYPE_C 0x1cc0U +#define ICEPICK_TYPE_D 0xb3d0U + +#define ICEPICK_MAJOR_SHIFT 28U +#define ICEPICK_MAJOR_MASK 0xfU +#define ICEPICK_MINOR_SHIFT 24U +#define ICEPICK_MINOR_MASK 0xfU + +void icepick_router_handler(const uint8_t dev_index) +{ + /* Switch the ICEPick TAP into its controller identification mode */ + jtag_dev_write_ir(dev_index, IR_ICEPICKCODE); + /* Then read out the 32-bit controller ID code */ + uint32_t icepick_idcode = 0U; + jtag_dev_shift_dr(dev_index, (uint8_t *)&icepick_idcode, NULL, 32U); + + /* Check it's a suitable ICEPick controller, and abort if not */ + if ((icepick_idcode & ICEPICK_TYPE_MASK) != ICEPICK_TYPE_D) { + DEBUG_ERROR("ICEPick is not a type-D controller (%08" PRIx32 ")\n", icepick_idcode); + return; + } + DEBUG_INFO("ICEPick type-D controller v%u.%u (%08" PRIx32 ")\n", + (icepick_idcode >> ICEPICK_MAJOR_SHIFT) & ICEPICK_MAJOR_MASK, + (icepick_idcode >> ICEPICK_MINOR_SHIFT) & ICEPICK_MINOR_MASK, icepick_idcode); +} diff --git a/src/target/icepick.h b/src/target/icepick.h new file mode 100644 index 00000000000..8e50f67aa0c --- /dev/null +++ b/src/target/icepick.h @@ -0,0 +1,41 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2023 1BitSquared + * Written by Rachel Mant + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TARGET_ICEPICK_H +#define TARGET_ICEPICK_H + +#include + +void icepick_router_handler(uint8_t dev_index); + +#endif /* TARGET_ICEPICK_H */ diff --git a/src/target/jtag_devs.c b/src/target/jtag_devs.c index ecd6eca761a..b7067b90823 100644 --- a/src/target/jtag_devs.c +++ b/src/target/jtag_devs.c @@ -24,6 +24,7 @@ #include "jtag_scan.h" #include "adiv5.h" #include "riscv_debug.h" +#include "icepick.h" #include "jtag_devs.h" const jtag_dev_descr_s dev_descr[] = { @@ -414,13 +415,14 @@ const jtag_dev_descr_s dev_descr[] = { .handler = riscv_jtag_dtm_handler, }, #endif -#if defined(CONFIG_CORTEXAR) // && defined(ENABLE_SITARA) +#if defined(CONFIG_CORTEXAR) && defined(ENABLE_TI_SITARA) { .idcode = 0x0b90002fU, .idmask = 0x0ff00fffU, #if ENABLE_DEBUG == 1 .descr = "TI ICEPick.", #endif + .handler = icepick_router_handler, }, #endif #if ENABLE_DEBUG == 1 diff --git a/src/target/meson.build b/src/target/meson.build index 4d37805121b..ee3820df053 100644 --- a/src/target/meson.build +++ b/src/target/meson.build @@ -357,7 +357,7 @@ target_at32f4 = declare_dependency( dependencies: [target_cortexm, target_stm_common] ) -target_ti = declare_dependency( +target_ti_cortexm = declare_dependency( sources: files( 'lmi.c', 'msp432e4.c', @@ -368,6 +368,23 @@ target_ti = declare_dependency( dependencies: target_cortexm, ) +target_ti_cortexa = declare_dependency( + sources: files( + 'icepick.c' + ), + dependencies: target_cortexar, + compile_args: ['-DENABLE_TI_SITARA=1'], +) +# If the Cortex-A/R target is not enabled, don't enable TI AM335x part support +if enabled_targets.contains('cortexar') + target_ti = [ + target_ti_cortexm, + target_ti_cortexa, + ] +else + target_ti = target_ti_cortexm +endif + target_xilinx = declare_dependency( sources: files( 'zynq7000.c', @@ -433,7 +450,8 @@ libbmd_target_deps = [ target_rp, target_sam, target_stm, - target_ti, + target_ti_cortexm, + target_ti_cortexa, target_xilinx, ] From c11eecfcfd52c018f9d0421ce8ae1fa19ddfc254 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 23 Jan 2024 12:32:39 +0000 Subject: [PATCH 02/27] icepick: Implemented a custom routine for writing the IR of the ICEPick as we have to avoid going into Idle with it --- src/target/icepick.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/target/icepick.c b/src/target/icepick.c index 243640dce26..2c9a6672949 100644 --- a/src/target/icepick.c +++ b/src/target/icepick.c @@ -41,6 +41,7 @@ */ #include "general.h" +#include "buffer_utils.h" #include "jtag_scan.h" #include "jtagtap.h" #include "icepick.h" @@ -62,10 +63,14 @@ #define ICEPICK_MINOR_SHIFT 24U #define ICEPICK_MINOR_MASK 0xfU +void icepick_write_ir(jtag_dev_s *device, uint8_t ir); + void icepick_router_handler(const uint8_t dev_index) { + jtag_dev_s *const device = &jtag_devs[dev_index]; + /* Switch the ICEPick TAP into its controller identification mode */ - jtag_dev_write_ir(dev_index, IR_ICEPICKCODE); + icepick_write_ir(device, IR_ICEPICKCODE); /* Then read out the 32-bit controller ID code */ uint32_t icepick_idcode = 0U; jtag_dev_shift_dr(dev_index, (uint8_t *)&icepick_idcode, NULL, 32U); @@ -79,3 +84,23 @@ void icepick_router_handler(const uint8_t dev_index) (icepick_idcode >> ICEPICK_MAJOR_SHIFT) & ICEPICK_MAJOR_MASK, (icepick_idcode >> ICEPICK_MINOR_SHIFT) & ICEPICK_MINOR_MASK, icepick_idcode); } + +void icepick_write_ir(jtag_dev_s *const device, const uint8_t ir) +{ + /* Set all the other devices IR's to being in bypass */ + for (size_t device_index = 0; device_index < jtag_dev_count; device_index++) + jtag_devs[device_index].current_ir = UINT32_MAX; + /* Put the current device IR into the requested state */ + device->current_ir = ir; + + /* Do the work to make the scanchain match the jtag_devs state */ + jtagtap_shift_ir(); + /* Once in Shift-IR, clock out 1's till we hit the right device in the chain */ + jtag_proc.jtagtap_tdi_seq(false, ones, device->ir_prescan); + /* Then clock out the new IR value and drop into Exit1-IR on the last cycle if we're the last device */ + jtag_proc.jtagtap_tdi_seq(!device->ir_postscan, &ir, device->ir_len); + /* Make sure we're in Exit1-IR having clocked out 1's for any more devices on the chain */ + jtag_proc.jtagtap_tdi_seq(true, ones, device->ir_postscan); + /* Now go to Update-IR but do not go back to Idle */ + jtagtap_return_idle(0); +} From 92ec07b6c8b334346ca684485cbe103578af85f2 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 23 Jan 2024 12:33:52 +0000 Subject: [PATCH 03/27] icepick: Implemented a custom routine for shifting the DR of the ICEPick as we have to avoid going into Idle with it --- src/target/icepick.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/target/icepick.c b/src/target/icepick.c index 2c9a6672949..635fe94f1fc 100644 --- a/src/target/icepick.c +++ b/src/target/icepick.c @@ -64,6 +64,7 @@ #define ICEPICK_MINOR_MASK 0xfU void icepick_write_ir(jtag_dev_s *device, uint8_t ir); +uint32_t icepick_shift_dr(const jtag_dev_s *device, uint32_t data_in, size_t clock_cycles); void icepick_router_handler(const uint8_t dev_index) { @@ -72,8 +73,7 @@ void icepick_router_handler(const uint8_t dev_index) /* Switch the ICEPick TAP into its controller identification mode */ icepick_write_ir(device, IR_ICEPICKCODE); /* Then read out the 32-bit controller ID code */ - uint32_t icepick_idcode = 0U; - jtag_dev_shift_dr(dev_index, (uint8_t *)&icepick_idcode, NULL, 32U); + const uint32_t icepick_idcode = icepick_shift_dr(device, 0U, 32U); /* Check it's a suitable ICEPick controller, and abort if not */ if ((icepick_idcode & ICEPICK_TYPE_MASK) != ICEPICK_TYPE_D) { @@ -104,3 +104,22 @@ void icepick_write_ir(jtag_dev_s *const device, const uint8_t ir) /* Now go to Update-IR but do not go back to Idle */ jtagtap_return_idle(0); } + +uint32_t icepick_shift_dr(const jtag_dev_s *const device, const uint32_t data_in, const size_t clock_cycles) +{ + /* Prepare the data to send */ + uint8_t data[4]; + write_le4(data, 0, data_in); + /* Switch into Shift-DR */ + jtagtap_shift_dr(); + /* Now we're in Shift-DR, clock out 1's till we hit the right device in the chain */ + jtag_proc.jtagtap_tdi_seq(false, ones, device->dr_prescan); + /* Now clock out the new DR value and get the response */ + jtag_proc.jtagtap_tdi_tdo_seq(data, !device->dr_postscan, data, clock_cycles); + /* Make sure we're in Exit1-DR having clocked out 1's for any more devices on the chain */ + jtag_proc.jtagtap_tdi_seq(true, ones, device->dr_postscan); + /* Now go to Update-DR but do not go back to Idle */ + jtagtap_return_idle(0); + /* Extract the resulting data */ + return read_le4(data, 0); +} From 1af653c36ab32b27e3d8e1464e5b3c4e9be4046a Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 22 Jan 2024 18:39:54 +0000 Subject: [PATCH 04/27] icepick: Implemented reading out the ICEPick configuration registers --- src/target/icepick.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/target/icepick.c b/src/target/icepick.c index 635fe94f1fc..93e0b6970e7 100644 --- a/src/target/icepick.c +++ b/src/target/icepick.c @@ -47,6 +47,7 @@ #include "icepick.h" #define IR_ROUTER 0x02U +#define IR_IDCODE 0x04U #define IR_ICEPICKCODE 0x05U #define IR_CONNECT 0x07U @@ -63,8 +64,29 @@ #define ICEPICK_MINOR_SHIFT 24U #define ICEPICK_MINOR_MASK 0xfU +#define ICEPICK_ROUTING_REG_MASK 0x7fU +#define ICEPICK_ROUTING_REG_SHIFT 24U +#define ICEPICK_ROUTING_DATA_MASK 0x00ffffffU +#define ICEPICK_ROUTING_RNW_MASK 0x80000000U +#define ICEPICK_ROUTING_RNW_WRITE 0x80000000U +#define ICEPICK_ROUTING_FAIL 0x80000000U + +#define ICEPICK_ROUTING_SYSCTRL 0x01U +#define ICEPICK_ROUTING_DEBUG_TAP_BASE 0x20U +#define ICEPICK_ROUTING_DEBUG_TAP_COUNT 16U + +/* + * The connect register is 8 bits long and has the following format: + * [0:3] - Connect key (9 to connect, anything else to disconnect) + * [4:6] - Reserved, RAZ/WI + * [7] - Write Enable, 1 to enable writing this register + */ +#define ICEPICK_CONNECT 0x89U +#define ICEPICK_DISCONNECT 0x80U + void icepick_write_ir(jtag_dev_s *device, uint8_t ir); uint32_t icepick_shift_dr(const jtag_dev_s *device, uint32_t data_in, size_t clock_cycles); +static void icepick_configure(const jtag_dev_s *device); void icepick_router_handler(const uint8_t dev_index) { @@ -83,6 +105,46 @@ void icepick_router_handler(const uint8_t dev_index) DEBUG_INFO("ICEPick type-D controller v%u.%u (%08" PRIx32 ")\n", (icepick_idcode >> ICEPICK_MAJOR_SHIFT) & ICEPICK_MAJOR_MASK, (icepick_idcode >> ICEPICK_MINOR_SHIFT) & ICEPICK_MINOR_MASK, icepick_idcode); + + /* Connect to the controller so we can modify the scan chain */ + icepick_write_ir(device, IR_CONNECT); + icepick_shift_dr(device, ICEPICK_CONNECT, 8U); + + /* Now we're connected, go into the routing inspection/modification mode */ + icepick_write_ir(device, IR_ROUTER); + /* Configure the router to put the Cortex TAP(s) on chain */ + icepick_configure(device); + /* Go to an idle state instruction and then run 10 idle cycles to complete reconfiguration */ + icepick_write_ir(device, IR_IDCODE); + jtag_proc.jtagtap_cycle(false, false, 10U); +} + +/* Read an ICEPick routing register */ +static bool icepick_read_reg(const jtag_dev_s *const device, const uint8_t reg, uint32_t *const result) +{ + /* Start by building a read request and sending it to the controller */ + icepick_shift_dr(device, (uint32_t)(reg & ICEPICK_ROUTING_REG_MASK) << ICEPICK_ROUTING_REG_SHIFT, 32U); + /* Having completed this, now do a dummy request to reg 0 to find out what the response is */ + const uint32_t value = icepick_shift_dr(device, 0U, 32U); + /* Now check if the request failed */ + if (value & ICEPICK_ROUTING_FAIL) + return false; + /* It did not, so now extract the data portion of the result */ + *result = value & ICEPICK_ROUTING_DATA_MASK; + return true; +} + +static void icepick_configure(const jtag_dev_s *const device) +{ + /* Try to read out the system control register */ + uint32_t sysctrl = 0U; + if (!icepick_read_reg(device, ICEPICK_ROUTING_SYSCTRL, &sysctrl)) { + DEBUG_ERROR("Failed to read ICEPick System Control register\n"); + return; + } + + /* Decode the register to determine what we've got */ + DEBUG_INFO("ICEPick sysctrl = %08" PRIx32 "\n", sysctrl); } void icepick_write_ir(jtag_dev_s *const device, const uint8_t ir) From f154ed27340c34b02ba21fac6ee626342c57f9c5 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 23 Jan 2024 11:43:50 +0000 Subject: [PATCH 05/27] icepick: Implemented writing ICEPick configuration registers --- src/target/icepick.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/target/icepick.c b/src/target/icepick.c index 93e0b6970e7..9da1602f1f4 100644 --- a/src/target/icepick.c +++ b/src/target/icepick.c @@ -75,6 +75,12 @@ #define ICEPICK_ROUTING_DEBUG_TAP_BASE 0x20U #define ICEPICK_ROUTING_DEBUG_TAP_COUNT 16U +#define ICEPICK_ROUTING_SYSCTRL_FREE_RUNNING_TCK 0x00001000U +#define ICEPICK_ROUTING_SYSCTRL_KEEP_POWERED 0x00000080U +#define ICEPICK_ROUTING_SYSCTRL_TDO_ALWAYS_OUT 0x00000020U +#define ICEPICK_ROUTING_SYSCTRL_DEVICE_TYPE_MASK 0x0000000eU +#define ICEPICK_ROUTING_SYSCTRL_SYSTEM_RESET 0x00000001U + /* * The connect register is 8 bits long and has the following format: * [0:3] - Connect key (9 to connect, anything else to disconnect) @@ -134,6 +140,20 @@ static bool icepick_read_reg(const jtag_dev_s *const device, const uint8_t reg, return true; } +/* Write an ICEPick routing register */ +static bool icepick_write_reg(const jtag_dev_s *const device, const uint8_t reg, const uint32_t value) +{ + /* Build a write a request and send it to the controller */ + icepick_shift_dr(device, + ICEPICK_ROUTING_RNW_WRITE | ((uint32_t)(reg & ICEPICK_ROUTING_REG_MASK) << ICEPICK_ROUTING_REG_SHIFT) | + (value & ICEPICK_ROUTING_DATA_MASK), + 32U); + /* Having completed this, now do a dummy request to reg 0 to find out what the response is */ + const uint32_t result = icepick_shift_dr(device, 0U, 32U); + /* Now check if the request failed */ + return !(result & ICEPICK_ROUTING_FAIL); +} + static void icepick_configure(const jtag_dev_s *const device) { /* Try to read out the system control register */ @@ -145,6 +165,16 @@ static void icepick_configure(const jtag_dev_s *const device) /* Decode the register to determine what we've got */ DEBUG_INFO("ICEPick sysctrl = %08" PRIx32 "\n", sysctrl); + /* + * Make sure the controller is set up for non-free-running TCK, that will be reset + * when doing a test logic reset, and that TDO is always an output + */ + sysctrl &= ~(ICEPICK_ROUTING_SYSCTRL_FREE_RUNNING_TCK | ICEPICK_ROUTING_SYSCTRL_KEEP_POWERED | + ICEPICK_ROUTING_SYSCTRL_TDO_ALWAYS_OUT); + if (!icepick_write_reg(device, ICEPICK_ROUTING_SYSCTRL, sysctrl)) { + DEBUG_ERROR("Failed to configure ICEPick\n"); + return; + } } void icepick_write_ir(jtag_dev_s *const device, const uint8_t ir) From 1a2a67cb11a219cea7d93602da3f9fac04c87ae9 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 23 Jan 2024 11:51:11 +0000 Subject: [PATCH 06/27] icepick: Implemented logic for scanning through and activating all available TAPs on the ICEPick --- src/target/icepick.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/target/icepick.c b/src/target/icepick.c index 9da1602f1f4..ee3002e6d45 100644 --- a/src/target/icepick.c +++ b/src/target/icepick.c @@ -81,6 +81,13 @@ #define ICEPICK_ROUTING_SYSCTRL_DEVICE_TYPE_MASK 0x0000000eU #define ICEPICK_ROUTING_SYSCTRL_SYSTEM_RESET 0x00000001U +#define ICEPICK_ROUTING_DEBUG_TAP_POWER_LOST 0x00200000U +#define ICEPICK_ROUTING_DEBUG_TAP_INHIBIT_SLEEP 0x00100000U +#define ICEPICK_ROUTING_DEBUG_TAP_RELEASE_WIR 0x00020000U +#define ICEPICK_ROUTING_DEBUG_TAP_DEBUG_ENABLE 0x00002000U +#define ICEPICK_ROUTING_DEBUG_TAP_SELECT 0x00000100U +#define ICEPICK_ROUTING_DEBUG_TAP_FORCE_ACTIVE 0x00000008U + /* * The connect register is 8 bits long and has the following format: * [0:3] - Connect key (9 to connect, anything else to disconnect) @@ -175,6 +182,19 @@ static void icepick_configure(const jtag_dev_s *const device) DEBUG_ERROR("Failed to configure ICEPick\n"); return; } + + for (uint8_t tap = 0U; tap < ICEPICK_ROUTING_DEBUG_TAP_COUNT; ++tap) { + uint32_t tap_config = 0U; + if (icepick_read_reg(device, ICEPICK_ROUTING_DEBUG_TAP_BASE + tap, &tap_config)) { + DEBUG_INFO("ICEPick TAP %u: %06" PRIx32 "\n", tap, tap_config); + if (!icepick_write_reg(device, ICEPICK_ROUTING_DEBUG_TAP_BASE + tap, + ICEPICK_ROUTING_DEBUG_TAP_POWER_LOST | ICEPICK_ROUTING_DEBUG_TAP_INHIBIT_SLEEP | + ICEPICK_ROUTING_DEBUG_TAP_RELEASE_WIR | ICEPICK_ROUTING_DEBUG_TAP_DEBUG_ENABLE | + ICEPICK_ROUTING_DEBUG_TAP_SELECT | ICEPICK_ROUTING_DEBUG_TAP_FORCE_ACTIVE)) + DEBUG_ERROR("ICEPick TAP %u write failed\n", tap); + } else + DEBUG_PROBE("ICEPick TAP %u read failed\n", tap); + } } void icepick_write_ir(jtag_dev_s *const device, const uint8_t ir) From a58d32d26aaf6ea10d257440bb7811f69948f3f2 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 23 Jan 2024 15:23:21 +0000 Subject: [PATCH 07/27] icepick: Implemented configuration logic for the cores attached via the ICEPick --- src/target/icepick.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/target/icepick.c b/src/target/icepick.c index ee3002e6d45..3488c961a9b 100644 --- a/src/target/icepick.c +++ b/src/target/icepick.c @@ -74,6 +74,8 @@ #define ICEPICK_ROUTING_SYSCTRL 0x01U #define ICEPICK_ROUTING_DEBUG_TAP_BASE 0x20U #define ICEPICK_ROUTING_DEBUG_TAP_COUNT 16U +#define ICEPICK_ROUTING_CORE_BASE 0x60U +#define ICEPICK_ROUTING_CORE_COUNT 16U #define ICEPICK_ROUTING_SYSCTRL_FREE_RUNNING_TCK 0x00001000U #define ICEPICK_ROUTING_SYSCTRL_KEEP_POWERED 0x00000080U @@ -195,6 +197,16 @@ static void icepick_configure(const jtag_dev_s *const device) } else DEBUG_PROBE("ICEPick TAP %u read failed\n", tap); } + + for (uint8_t core = 0; core < ICEPICK_ROUTING_CORE_COUNT; ++core) { + uint32_t core_config = 0U; + if (icepick_read_reg(device, ICEPICK_ROUTING_CORE_BASE + core, &core_config)) { + DEBUG_INFO("ICEPick core %u: %06" PRIx32 "\n", core, core_config); + if (!icepick_write_reg(device, ICEPICK_ROUTING_CORE_BASE + core, 0x00002008U)) + DEBUG_ERROR("ICEPick core %u write failed\n", core); + } else + DEBUG_PROBE("ICEPick core %u read failed\n", core); + } } void icepick_write_ir(jtag_dev_s *const device, const uint8_t ir) From 88786ea0b10c916ccd2935c633a4c2b7fa1e8d3a Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 23 Jan 2024 23:06:34 +0000 Subject: [PATCH 08/27] icepick: Handle the re-scan portion of the ICEPick operations --- src/target/icepick.c | 4 ++++ src/target/jtag_scan.c | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/target/icepick.c b/src/target/icepick.c index 3488c961a9b..44f59cc5ce3 100644 --- a/src/target/icepick.c +++ b/src/target/icepick.c @@ -105,6 +105,8 @@ static void icepick_configure(const jtag_dev_s *device); void icepick_router_handler(const uint8_t dev_index) { + if (dev_index >= 2U) + return; jtag_dev_s *const device = &jtag_devs[dev_index]; /* Switch the ICEPick TAP into its controller identification mode */ @@ -132,6 +134,8 @@ void icepick_router_handler(const uint8_t dev_index) /* Go to an idle state instruction and then run 10 idle cycles to complete reconfiguration */ icepick_write_ir(device, IR_IDCODE); jtag_proc.jtagtap_cycle(false, false, 10U); + /* Now re-scan the bus to pick up all the new TAPs */ + jtag_discover(); } /* Read an ICEPick routing register */ diff --git a/src/target/jtag_scan.c b/src/target/jtag_scan.c index 09cadba4807..eb70b50b4a5 100644 --- a/src/target/jtag_scan.c +++ b/src/target/jtag_scan.c @@ -143,7 +143,8 @@ bool jtag_scan(void) #endif /* Check for known devices and handle accordingly */ - for (size_t device = 0; device < jtag_dev_count; device++) { + const size_t devices = jtag_dev_count; + for (size_t device = 0; device < devices; device++) { for (size_t descr = 0; dev_descr[descr].idcode; descr++) { if ((jtag_devs[device].jd_idcode & dev_descr[descr].idmask) == dev_descr[descr].idcode) { /* Call handler to initialise/probe device further */ @@ -154,7 +155,7 @@ bool jtag_scan(void) } } - return jtag_dev_count > 0; + return devices > 0; } static bool jtag_read_idcodes(void) From c4b6549131740d3f15f885997534b83f0a02f647 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Fri, 26 Jan 2024 00:40:27 +0000 Subject: [PATCH 09/27] am335x: Implemented identification of the Cortex-M3 part of the processor --- src/target/am335x.c | 63 +++++++++++++++++++++++++++++++++++++++ src/target/cortexm.c | 1 + src/target/meson.build | 1 + src/target/target_probe.c | 1 + src/target/target_probe.h | 1 + 5 files changed, 67 insertions(+) create mode 100644 src/target/am335x.c diff --git a/src/target/am335x.c b/src/target/am335x.c new file mode 100644 index 00000000000..52101ffd330 --- /dev/null +++ b/src/target/am335x.c @@ -0,0 +1,63 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2024 1BitSquared + * Written by Rachel Mant + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file implements support for AM355x series devices, providing memory + * maps and Flash programming routines. + * + * References: + * SPRUH73Q - AM335x and AMIC110 Sitara™ Processors + * https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf + */ + +#include "general.h" +#include "target.h" +#include "target_internal.h" +#include "cortex.h" + +#define AM335x_CTRL_BASE 0x44e10000U +#define AM335x_CTRL_DEVICE_ID (AM335x_CTRL_BASE + 0x600U) + +#define AM335x_CTRL_DEVICE_ID_MASK 0x0fffffffU +#define AM335x_CTRL_DEVICE_ID_AM335x 0x0b94402eU + +bool am335x_cm3_probe(target_s *const target) +{ + /* Try to read out the device identification register and check this is actually an AM335x device */ + const uint32_t device_id = target_mem_read32(target, AM335x_CTRL_DEVICE_ID) & AM335x_CTRL_DEVICE_ID_MASK; + if (device_id != AM335x_CTRL_DEVICE_ID_AM335x) + return false; + + cortex_ap(target)->dp->quirks |= ADIV5_DP_QUIRK_DUPED_AP; + return true; +} diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 71b571b4fde..0acef62e707 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -501,6 +501,7 @@ bool cortexm_probe(adiv5_access_port_s *ap) PROBE(ke04_probe); PROBE(lpc17xx_probe); PROBE(lpc11xx_probe); /* LPC1343 */ + PROBE(am335x_cm3_probe); break; } #if CONFIG_BMDA == 0 diff --git a/src/target/meson.build b/src/target/meson.build index ee3820df053..f7c488217f1 100644 --- a/src/target/meson.build +++ b/src/target/meson.build @@ -370,6 +370,7 @@ target_ti_cortexm = declare_dependency( target_ti_cortexa = declare_dependency( sources: files( + 'am335x.c', 'icepick.c' ), dependencies: target_cortexar, diff --git a/src/target/target_probe.c b/src/target/target_probe.c index 0171dccb644..ecdb38e3ec7 100644 --- a/src/target/target_probe.c +++ b/src/target/target_probe.c @@ -103,6 +103,7 @@ CORTEXM_PROBE_WEAK_NOP(nrf51_ctrl_ap_probe) CORTEXM_PROBE_WEAK_NOP(nrf54l_ctrl_ap_probe) CORTEXM_PROBE_WEAK_NOP(rp2040_rescue_probe) +TARGET_PROBE_WEAK_NOP(am335x_cm3_probe) TARGET_PROBE_WEAK_NOP(apollo_3_probe) TARGET_PROBE_WEAK_NOP(at32f40x_probe) TARGET_PROBE_WEAK_NOP(at32f43x_probe) diff --git a/src/target/target_probe.h b/src/target/target_probe.h index 9c906cb3ef0..04e9b2f2fac 100644 --- a/src/target/target_probe.h +++ b/src/target/target_probe.h @@ -54,6 +54,7 @@ bool nrf51_ctrl_ap_probe(adiv5_access_port_s *ap); bool nrf54l_ctrl_ap_probe(adiv5_access_port_s *ap); bool rp2040_rescue_probe(adiv5_access_port_s *ap); +bool am335x_cm3_probe(target_s *target); bool at32f40x_probe(target_s *target); // STM32 clones from Artery bool apollo_3_probe(target_s *target); bool at32f43x_probe(target_s *target); From d5b156379bc9e4ce5072f4d5f722e611e2e31c10 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Thu, 30 Jan 2025 18:09:02 +0900 Subject: [PATCH 10/27] dap_jtag: add dap_jtag_cycle for CMSIS-DAP devices Add a dap_jtag_cycle() function for CMSIS-DAP. This fixes JTAG running on CMSIS-DAP devices. Signed-off-by: Sean Cross --- src/platforms/hosted/dap_jtag.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/platforms/hosted/dap_jtag.c b/src/platforms/hosted/dap_jtag.c index bc677128618..9cc7e7b2e45 100644 --- a/src/platforms/hosted/dap_jtag.c +++ b/src/platforms/hosted/dap_jtag.c @@ -41,6 +41,7 @@ static void dap_jtag_tms_seq(uint32_t tms_states, size_t clock_cycles); static void dap_jtag_tdi_tdo_seq(uint8_t *data_out, bool final_tms, const uint8_t *data_in, size_t clock_cycles); static void dap_jtag_tdi_seq(bool final_tms, const uint8_t *data_in, size_t clock_cycles); static bool dap_jtag_next(bool tms, bool tdi); +static void dap_jtag_cycle(const bool tms, const bool tdi, const size_t clock_cycles); bool dap_jtag_init(void) { @@ -58,6 +59,7 @@ bool dap_jtag_init(void) jtag_proc.jtagtap_tms_seq = dap_jtag_tms_seq; jtag_proc.jtagtap_tdi_tdo_seq = dap_jtag_tdi_tdo_seq; jtag_proc.jtagtap_tdi_seq = dap_jtag_tdi_seq; + jtag_proc.jtagtap_cycle = dap_jtag_cycle; /* Ensure we're in JTAG mode */ for (size_t i = 0; i <= 50U; ++i) @@ -145,3 +147,9 @@ bool dap_jtag_configure(void) DEBUG_ERROR("dap_jtag_configure failed with %02x\n", response); return response == DAP_RESPONSE_OK; } + +static void dap_jtag_cycle(const bool tms, const bool tdi, const size_t clock_cycles) +{ + for (size_t cycle = 0U; cycle < clock_cycles; ++cycle) + dap_jtag_next(tms, tdi); +} From 67470d120bf020ceb66e7aef8364e2e794525450 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Thu, 30 Jan 2025 18:10:58 +0900 Subject: [PATCH 11/27] rename target_mem_read32 -> target_mem32_read32 This function was renamed, but these files weren't updated. Signed-off-by: Sean Cross --- src/target/am335x.c | 2 +- src/target/samx5x.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/target/am335x.c b/src/target/am335x.c index 52101ffd330..49fc39e7a0d 100644 --- a/src/target/am335x.c +++ b/src/target/am335x.c @@ -54,7 +54,7 @@ bool am335x_cm3_probe(target_s *const target) { /* Try to read out the device identification register and check this is actually an AM335x device */ - const uint32_t device_id = target_mem_read32(target, AM335x_CTRL_DEVICE_ID) & AM335x_CTRL_DEVICE_ID_MASK; + const uint32_t device_id = target_mem32_read32(target, AM335x_CTRL_DEVICE_ID) & AM335x_CTRL_DEVICE_ID_MASK; if (device_id != AM335x_CTRL_DEVICE_ID_AM335x) return false; diff --git a/src/target/samx5x.c b/src/target/samx5x.c index e36c08cf86a..26c5233921e 100644 --- a/src/target/samx5x.c +++ b/src/target/samx5x.c @@ -890,7 +890,7 @@ static bool samx5x_cmd_update_user_word(target_s *t, int argc, const char **argv static uint32_t samx5x_ram_size(target_s *t) { /* Read the Device ID */ - const uint32_t did = target_mem_read32(t, SAMX5X_DSU_DID); + const uint32_t did = target_mem32_read32(t, SAMX5X_DSU_DID); /* Mask off the device select bits */ const samx5x_descr_s samx5x = samx5x_parse_device_id(did); /* Adjust the maximum ram size (256KB) down as appropriate */ @@ -926,7 +926,7 @@ static bool samx5x_cmd_mbist(target_s *t, int argc, const char **argv) /* Poll for DSU Ready */ uint32_t status = 0; while ((status & (SAMX5X_STATUSA_DONE | SAMX5X_STATUSA_PERR | SAMX5X_STATUSA_FAIL)) == 0U) { - status = target_mem_read32(t, SAMX5X_DSU_CTRLSTAT); + status = target_mem32_read32(t, SAMX5X_DSU_CTRLSTAT); if (target_check_error(t)) return false; } @@ -939,8 +939,8 @@ static bool samx5x_cmd_mbist(target_s *t, int argc, const char **argv) /* Test the fail bit in Status A */ if (status & SAMX5X_STATUSA_FAIL) { - const uint32_t data = target_mem_read32(t, SAMX5X_DSU_DATA); - tc_printf(t, "MBIST Fail @ 0x%08" PRIx32 " (bit %u in phase %u)\n", target_mem_read32(t, SAMX5X_DSU_ADDRESS), + const uint32_t data = target_mem32_read32(t, SAMX5X_DSU_DATA); + tc_printf(t, "MBIST Fail @ 0x%08" PRIx32 " (bit %u in phase %u)\n", target_mem32_read32(t, SAMX5X_DSU_ADDRESS), data & 0x1fU, data >> 8U); } else tc_printf(t, "MBIST Passed!\n"); From a5113e55de5fc419c747ed72bd61d77064aa4fe6 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Thu, 30 Jan 2025 18:11:45 +0900 Subject: [PATCH 12/27] icepick: support type c icepick devies This is now able to enable the TMS570 board. Signed-off-by: Sean Cross --- src/target/icepick.c | 59 +++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/src/target/icepick.c b/src/target/icepick.c index 44f59cc5ce3..f8fc67d5252 100644 --- a/src/target/icepick.c +++ b/src/target/icepick.c @@ -64,6 +64,9 @@ #define ICEPICK_MINOR_SHIFT 24U #define ICEPICK_MINOR_MASK 0xfU +#define ICEPICK_TESTAPS_SHIFT 20 +#define ICEPICK_TESTAPS_MASK 7 + #define ICEPICK_ROUTING_REG_MASK 0x7fU #define ICEPICK_ROUTING_REG_SHIFT 24U #define ICEPICK_ROUTING_DATA_MASK 0x00ffffffU @@ -99,9 +102,9 @@ #define ICEPICK_CONNECT 0x89U #define ICEPICK_DISCONNECT 0x80U -void icepick_write_ir(jtag_dev_s *device, uint8_t ir); -uint32_t icepick_shift_dr(const jtag_dev_s *device, uint32_t data_in, size_t clock_cycles); -static void icepick_configure(const jtag_dev_s *device); +static void icepick_write_ir(jtag_dev_s *device, uint8_t ir); +static uint32_t icepick_shift_dr(const jtag_dev_s *device, uint32_t data_in, size_t clock_cycles); +static void icepick_configure(jtag_dev_s *device, char icepick_type, uint32_t tap_count); void icepick_router_handler(const uint8_t dev_index) { @@ -113,13 +116,25 @@ void icepick_router_handler(const uint8_t dev_index) icepick_write_ir(device, IR_ICEPICKCODE); /* Then read out the 32-bit controller ID code */ const uint32_t icepick_idcode = icepick_shift_dr(device, 0U, 32U); + char icepick_type; + uint32_t testaps_count; /* Check it's a suitable ICEPick controller, and abort if not */ - if ((icepick_idcode & ICEPICK_TYPE_MASK) != ICEPICK_TYPE_D) { - DEBUG_ERROR("ICEPick is not a type-D controller (%08" PRIx32 ")\n", icepick_idcode); + switch (icepick_idcode & ICEPICK_TYPE_MASK) { + case ICEPICK_TYPE_C: + icepick_type = 'C'; + testaps_count = (icepick_idcode >> ICEPICK_TESTAPS_SHIFT) & ICEPICK_TESTAPS_MASK; + break; + case ICEPICK_TYPE_D: + icepick_type = 'D'; + testaps_count = ICEPICK_ROUTING_DEBUG_TAP_COUNT; + break; + default: + DEBUG_ERROR("ICEPick is not a type-C or type-D controller (%08" PRIx32 ")\n", icepick_idcode); return; } - DEBUG_INFO("ICEPick type-D controller v%u.%u (%08" PRIx32 ")\n", + + DEBUG_INFO("ICEPick type-%c controller v%u.%u (%08" PRIx32 ")\n", icepick_type, (icepick_idcode >> ICEPICK_MAJOR_SHIFT) & ICEPICK_MAJOR_MASK, (icepick_idcode >> ICEPICK_MINOR_SHIFT) & ICEPICK_MINOR_MASK, icepick_idcode); @@ -130,7 +145,7 @@ void icepick_router_handler(const uint8_t dev_index) /* Now we're connected, go into the routing inspection/modification mode */ icepick_write_ir(device, IR_ROUTER); /* Configure the router to put the Cortex TAP(s) on chain */ - icepick_configure(device); + icepick_configure(device, icepick_type, testaps_count); /* Go to an idle state instruction and then run 10 idle cycles to complete reconfiguration */ icepick_write_ir(device, IR_IDCODE); jtag_proc.jtagtap_cycle(false, false, 10U); @@ -167,7 +182,7 @@ static bool icepick_write_reg(const jtag_dev_s *const device, const uint8_t reg, return !(result & ICEPICK_ROUTING_FAIL); } -static void icepick_configure(const jtag_dev_s *const device) +static void icepick_configure(jtag_dev_s *const device, char icepick_type, const uint32_t testaps_count) { /* Try to read out the system control register */ uint32_t sysctrl = 0U; @@ -189,12 +204,12 @@ static void icepick_configure(const jtag_dev_s *const device) return; } - for (uint8_t tap = 0U; tap < ICEPICK_ROUTING_DEBUG_TAP_COUNT; ++tap) { + for (uint8_t tap = 0U; tap < testaps_count; ++tap) { uint32_t tap_config = 0U; if (icepick_read_reg(device, ICEPICK_ROUTING_DEBUG_TAP_BASE + tap, &tap_config)) { DEBUG_INFO("ICEPick TAP %u: %06" PRIx32 "\n", tap, tap_config); if (!icepick_write_reg(device, ICEPICK_ROUTING_DEBUG_TAP_BASE + tap, - ICEPICK_ROUTING_DEBUG_TAP_POWER_LOST | ICEPICK_ROUTING_DEBUG_TAP_INHIBIT_SLEEP | + tap_config | ICEPICK_ROUTING_DEBUG_TAP_POWER_LOST | ICEPICK_ROUTING_DEBUG_TAP_INHIBIT_SLEEP | ICEPICK_ROUTING_DEBUG_TAP_RELEASE_WIR | ICEPICK_ROUTING_DEBUG_TAP_DEBUG_ENABLE | ICEPICK_ROUTING_DEBUG_TAP_SELECT | ICEPICK_ROUTING_DEBUG_TAP_FORCE_ACTIVE)) DEBUG_ERROR("ICEPick TAP %u write failed\n", tap); @@ -202,18 +217,22 @@ static void icepick_configure(const jtag_dev_s *const device) DEBUG_PROBE("ICEPick TAP %u read failed\n", tap); } - for (uint8_t core = 0; core < ICEPICK_ROUTING_CORE_COUNT; ++core) { - uint32_t core_config = 0U; - if (icepick_read_reg(device, ICEPICK_ROUTING_CORE_BASE + core, &core_config)) { - DEBUG_INFO("ICEPick core %u: %06" PRIx32 "\n", core, core_config); - if (!icepick_write_reg(device, ICEPICK_ROUTING_CORE_BASE + core, 0x00002008U)) - DEBUG_ERROR("ICEPick core %u write failed\n", core); - } else - DEBUG_PROBE("ICEPick core %u read failed\n", core); + icepick_write_ir(device, IR_IDCODE); + + if (icepick_type == 'D') { + for (uint8_t core = 0; core < ICEPICK_ROUTING_CORE_COUNT; ++core) { + uint32_t core_config = 0U; + if (icepick_read_reg(device, ICEPICK_ROUTING_CORE_BASE + core, &core_config)) { + DEBUG_INFO("ICEPick core %u: %06" PRIx32 "\n", core, core_config); + if (!icepick_write_reg(device, ICEPICK_ROUTING_CORE_BASE + core, 0x00002008U)) + DEBUG_ERROR("ICEPick core %u write failed\n", core); + } else + DEBUG_PROBE("ICEPick core %u read failed\n", core); + } } } -void icepick_write_ir(jtag_dev_s *const device, const uint8_t ir) +static void icepick_write_ir(jtag_dev_s *const device, const uint8_t ir) { /* Set all the other devices IR's to being in bypass */ for (size_t device_index = 0; device_index < jtag_dev_count; device_index++) @@ -233,7 +252,7 @@ void icepick_write_ir(jtag_dev_s *const device, const uint8_t ir) jtagtap_return_idle(0); } -uint32_t icepick_shift_dr(const jtag_dev_s *const device, const uint32_t data_in, const size_t clock_cycles) +static uint32_t icepick_shift_dr(const jtag_dev_s *const device, const uint32_t data_in, const size_t clock_cycles) { /* Prepare the data to send */ uint8_t data[4]; From d2197dd07de5563e13679de6dab9fdd3af230dca Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Thu, 30 Jan 2025 18:12:30 +0900 Subject: [PATCH 13/27] adi: add entries for Cortex-R5 Signed-off-by: Sean Cross --- src/target/adi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/target/adi.c b/src/target/adi.c index 054ac516c18..da81b9d4f90 100644 --- a/src/target/adi.c +++ b/src/target/adi.c @@ -120,6 +120,7 @@ static const arm_coresight_component_s arm_component_lut[] = { {0x924, 0x13, 0, aa_nosupport, cidc_unknown, ARM_COMPONENT_STR("Cortex-M3 ETM", "(Embedded Trace)")}, {0x925, 0x13, 0, aa_nosupport, cidc_unknown, ARM_COMPONENT_STR("Cortex-M4 ETM", "(Embedded Trace)")}, {0x930, 0x13, 0, aa_nosupport, cidc_unknown, ARM_COMPONENT_STR("Cortex-R4 ETM", "(Embedded Trace)")}, + {0x931, 0x13, 0, aa_nosupport, cidc_unknown, ARM_COMPONENT_STR("Cortex-R5 ETM", "(Embedded Trace)")}, {0x932, 0x31, 0x0a31, aa_nosupport, cidc_unknown, ARM_COMPONENT_STR("CoreSight MTB-M0+", "(Simple Execution Trace)")}, {0x941, 0x00, 0, aa_nosupport, cidc_unknown, @@ -147,6 +148,7 @@ static const arm_coresight_component_s arm_component_lut[] = { {0xc09, 0x15, 0, aa_cortexa, cidc_dc, ARM_COMPONENT_STR("Cortex-A9", "(Debug Unit)")}, {0xc0f, 0x15, 0, aa_cortexa, cidc_unknown, ARM_COMPONENT_STR("Cortex-A15", "(Debug Unit)")}, {0xc14, 0x15, 0, aa_cortexr, cidc_unknown, ARM_COMPONENT_STR("Cortex-R4", "(Debug Unit)")}, + {0xc15, 0x15, 0, aa_cortexr, cidc_unknown, ARM_COMPONENT_STR("Cortex-R5", "(Debug Unit)")}, {0xcd0, 0x00, 0, aa_nosupport, cidc_unknown, ARM_COMPONENT_STR("Atmel DSU", "(Device Service Unit)")}, {0xd20, 0x00, 0x2a04, aa_cortexm, cidc_gipc, ARM_COMPONENT_STR("Cortex-M23", "(System Control Space)")}, {0xd20, 0x11, 0, aa_nosupport, cidc_dc, ARM_COMPONENT_STR("Cortex-M23", "(Trace Port Interface Unit)")}, From 02dee2171a67c31445b44623b128ff43c6922f85 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Thu, 30 Jan 2025 18:13:05 +0900 Subject: [PATCH 14/27] tms570: add basic support for TI TMS570 Signed-off-by: Sean Cross --- src/target/cortexar.c | 5 +++++ src/target/meson.build | 16 ++++++++++++++-- src/target/target_probe.c | 1 + src/target/target_probe.h | 1 + src/target/ti_tms570.c | 29 +++++++++++++++++++++++++++++ 5 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/target/ti_tms570.c diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 4ec6ad10806..0b3ea35ab6d 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -922,6 +922,11 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre if (!target) return false; + // TI omitted the designer code on TMS570. + if (target->designer_code == 0) { + PROBE(ti_tms570_probe); + } + #if CONFIG_BMDA == 0 gdb_outf("Please report unknown device with Designer 0x%x Part ID 0x%x\n", target->designer_code, target->part_id); #else diff --git a/src/target/meson.build b/src/target/meson.build index f7c488217f1..eb1cd900045 100644 --- a/src/target/meson.build +++ b/src/target/meson.build @@ -376,11 +376,22 @@ target_ti_cortexa = declare_dependency( dependencies: target_cortexar, compile_args: ['-DENABLE_TI_SITARA=1'], ) + +target_ti_cortexr = declare_dependency( + sources: files( + 'ti_tms570.c', + 'icepick.c' + ), + dependencies: target_cortexar, + compile_args: ['-DENABLE_TI_TMS570=1'], +) + # If the Cortex-A/R target is not enabled, don't enable TI AM335x part support -if enabled_targets.contains('cortexar') +if not is_firmware_build or enabled_targets.contains('cortexar') target_ti = [ target_ti_cortexm, target_ti_cortexa, + target_ti_cortexr, ] else target_ti = target_ti_cortexm @@ -451,8 +462,9 @@ libbmd_target_deps = [ target_rp, target_sam, target_stm, - target_ti_cortexm, target_ti_cortexa, + target_ti_cortexm, + target_ti_cortexr, target_xilinx, ] diff --git a/src/target/target_probe.c b/src/target/target_probe.c index ecdb38e3ec7..3993647f8a7 100644 --- a/src/target/target_probe.c +++ b/src/target/target_probe.c @@ -157,6 +157,7 @@ TARGET_PROBE_WEAK_NOP(stm32l4_probe) TARGET_PROBE_WEAK_NOP(stm32mp15_ca7_probe) TARGET_PROBE_WEAK_NOP(stm32mp15_cm4_probe) TARGET_PROBE_WEAK_NOP(stm32wb0_probe) +TARGET_PROBE_WEAK_NOP(ti_tms570_probe) TARGET_PROBE_WEAK_NOP(zynq7_probe) LPC55_DP_PREPARE_WEAK_NOP(lpc55_dp_prepare) diff --git a/src/target/target_probe.h b/src/target/target_probe.h index 04e9b2f2fac..9703fb607f6 100644 --- a/src/target/target_probe.h +++ b/src/target/target_probe.h @@ -108,6 +108,7 @@ bool stm32l4_probe(target_s *target); bool stm32mp15_ca7_probe(target_s *target); bool stm32mp15_cm4_probe(target_s *target); bool stm32wb0_probe(target_s *target); +bool ti_tms570_probe(target_s *target); bool zynq7_probe(target_s *target); void lpc55_dp_prepare(adiv5_debug_port_s *dp); diff --git a/src/target/ti_tms570.c b/src/target/ti_tms570.c new file mode 100644 index 00000000000..1cbdc09d24c --- /dev/null +++ b/src/target/ti_tms570.c @@ -0,0 +1,29 @@ +#include "general.h" +#include "target.h" +#include "target_internal.h" +#include "cortexar.h" + +#define TMS570_SYS_BASE 0xffffff00U +#define TMS570_SYS_DEVID (TMS570_SYS_BASE + 0xf0U) +#define TMS570_SCM_DEVID_ID_MASK 0x7ffe0007U +#define TMS570_SCM_REVID_ID_TMS570 0x00440005U + +/* Base address for the OCRAM regions, including their mirrors (including RETRAM) */ +#define TMS570_SRAM_BASE 0x08000000U +#define TMS570_SRAM_ECC_BASE 0x08400000U +#define TMS570_SRAM_SIZE 0x80000U + +#define TMS570_OTP_PACKAGE_AND_FLASH_MEMORY_SIZE 0xf008015cU + +bool ti_tms570_probe(target_s *const target) +{ + const uint32_t part_id = target_mem32_read32(target, TMS570_SYS_DEVID); + if (!part_id || ((part_id & TMS570_SCM_DEVID_ID_MASK) != TMS570_SCM_REVID_ID_TMS570)) { + return false; + } + + target->driver = "TMS570"; + target_add_ram32(target, TMS570_SRAM_BASE, TMS570_SRAM_SIZE); + target_add_ram32(target, TMS570_SRAM_ECC_BASE, TMS570_SRAM_SIZE); + return true; +} \ No newline at end of file From ee3ebab7cffe3d1d9c10f90c154c564d73123039 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Tue, 1 Apr 2025 14:55:12 +0800 Subject: [PATCH 15/27] cortexar: hack to get tms570 working This gets basic debugging working, including breakpoints, single-stepping, memory access, and register access. Signed-off-by: Sean Cross --- src/target/cortexar.c | 50 +++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 0b3ea35ab6d..ad620862dff 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -59,6 +59,19 @@ #include +static uint32_t swap32(const uint32_t value) +{ + return ((value >> 24) & 0xff) | ((value >> 8) & 0xff00) | ((value << 8) & 0xff0000) | ((value << 24) & 0xff000000); +} + +static void memcpy_swap(void *dest_v, const void *src_v, size_t count) { + uint8_t *dest = dest_v; + const uint8_t *src = src_v; + for (size_t i = 0; i < count; i += 1) { + dest[(i&~3)+(~i&3)] = src[i]; + } +} + typedef struct cortexar_priv { /* Base core information */ cortex_priv_s base; @@ -286,10 +299,10 @@ static const uint16_t cortexar_spsr_encodings[5] = { * The fourth is `STRH r1, [r0], #+2` to store a uint16_t to [r0] from r1 and increment * the address in r0 by 2, writing the new address back to r0. */ -#define ARM_LDRB_R0_R1_INSN 0xe4f01001U -#define ARM_LDRH_R0_R1_INSN 0xe0f010b2U -#define ARM_STRB_R1_R0_INSN 0xe4e01001U -#define ARM_STRH_R1_R0_INSN 0xe0e010b2U +#define ARM_LDRB_R0_R1_INSN 0xe4d01001U +#define ARM_LDRH_R0_R1_INSN 0xe0d010b2U +#define ARM_STRB_R1_R0_INSN 0xe4c01001U +#define ARM_STRH_R1_R0_INSN 0xe0c010b2U /* Instruction encodings for synchronisation barriers */ #define ARM_ISB_INSN 0xe57ff06fU @@ -1021,7 +1034,7 @@ static inline bool cortexar_mem_read_fast(target_s *const target, uint32_t *cons /* Run the transfer, hammering the DTR */ for (size_t offset = 0; offset < count; ++offset) { /* Read the next value, which is the value for the last instruction run */ - const uint32_t value = adiv5_dp_read(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DTRRX)); + const uint32_t value = swap32(adiv5_dp_read(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DTRRX))); /* If we've run the instruction at least once, store it */ if (offset) dest[offset - 1U] = value; @@ -1031,7 +1044,7 @@ static inline bool cortexar_mem_read_fast(target_s *const target, uint32_t *cons /* Go back into DCC Normal (Non-blocking) mode */ adiv5_dp_write(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DCSR), dbg_dcsr | CORTEXAR_DBG_DCSR_DCC_NORMAL); /* Grab the value of the last instruction run now it won't run again */ - dest[count - 1U] = adiv5_dp_read(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DTRRX)); + dest[count - 1U] = swap32(adiv5_dp_read(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DTRRX))); /* Check if the instruction triggered a synchronous data abort */ return cortexar_check_data_abort(target, status); } @@ -1040,6 +1053,7 @@ static inline bool cortexar_mem_read_fast(target_s *const target, uint32_t *cons for (size_t offset = 0; offset < count; ++offset) { if (!cortexar_run_read_insn(target, ARM_LDC_R0_POSTINC4_DTRTX_INSN, dest + offset)) return false; /* Propagate failure if it happens */ + dest[offset] = swap32(dest[offset]); } return true; /* Signal success */ } @@ -1165,7 +1179,7 @@ static inline bool cortexar_mem_write_fast(target_s *const target, const uint32_ adiv5_dp_write(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_ITR), ARM_STC_DTRRX_R0_POSTINC4_INSN); /* Run the transfer, hammering the DTR */ for (size_t offset = 0; offset < count; ++offset) - adiv5_dp_write(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DTRTX), src[offset]); + adiv5_dp_write(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DTRTX), swap32(src[offset])); /* Now read out the status from the DCSR in case anything went wrong */ const uint32_t status = adiv5_dp_read(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DCSR)); /* Go back into DCC Normal (Non-blocking) mode */ @@ -1176,7 +1190,7 @@ static inline bool cortexar_mem_write_fast(target_s *const target, const uint32_ /* Write each of the uint32_t's checking for failure */ for (size_t offset = 0; offset < count; ++offset) { - if (!cortexar_run_write_insn(target, ARM_STC_DTRRX_R0_POSTINC4_INSN, src[offset])) + if (!cortexar_run_write_insn(target, ARM_STC_DTRRX_R0_POSTINC4_INSN, swap32(src[offset]))) return false; /* Propagate failure if it happens */ } return true; /* Signal success */ @@ -1277,11 +1291,11 @@ static void cortexar_regs_read(target_s *const target, void *const data) const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; uint32_t *const regs = (uint32_t *)data; /* Copy the register values out from our cache */ - memcpy(regs, priv->core_regs.r, sizeof(priv->core_regs.r)); - regs[CORTEX_REG_CPSR] = priv->core_regs.cpsr; + memcpy_swap(regs, priv->core_regs.r, sizeof(priv->core_regs.r)); + regs[CORTEX_REG_CPSR] = swap32(priv->core_regs.cpsr); if (target->target_options & TOPT_FLAVOUR_FLOAT) { - memcpy(regs + CORTEXAR_GENERAL_REG_COUNT, priv->core_regs.d, sizeof(priv->core_regs.d)); - regs[CORTEX_REG_FPCSR] = priv->core_regs.fpcsr; + memcpy_swap(regs + CORTEXAR_GENERAL_REG_COUNT, priv->core_regs.d, sizeof(priv->core_regs.d)); + regs[CORTEX_REG_FPCSR] = swap32(priv->core_regs.fpcsr); } } @@ -1290,11 +1304,11 @@ static void cortexar_regs_write(target_s *const target, const void *const data) cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; const uint32_t *const regs = (const uint32_t *)data; /* Copy the new register values into our cache */ - memcpy(priv->core_regs.r, regs, sizeof(priv->core_regs.r)); - priv->core_regs.cpsr = regs[CORTEX_REG_CPSR]; + memcpy_swap(priv->core_regs.r, regs, sizeof(priv->core_regs.r)); + priv->core_regs.cpsr = swap32(regs[CORTEX_REG_CPSR]); if (target->target_options & TOPT_FLAVOUR_FLOAT) { - memcpy(priv->core_regs.d, regs + CORTEXAR_GENERAL_REG_COUNT, sizeof(priv->core_regs.d)); - priv->core_regs.fpcsr = regs[CORTEX_REG_FPCSR]; + memcpy_swap(priv->core_regs.d, regs + CORTEXAR_GENERAL_REG_COUNT, sizeof(priv->core_regs.d)); + priv->core_regs.fpcsr = swap32(regs[CORTEX_REG_FPCSR]); } } @@ -1339,7 +1353,7 @@ static size_t cortexar_reg_read(target_s *const target, const uint32_t reg, void if (max < reg_width) return 0; /* Finally, copy the register data out and return the width */ - memcpy(data, reg_ptr, reg_width); + memcpy_swap(data, reg_ptr, reg_width); return reg_width; } @@ -1354,7 +1368,7 @@ static size_t cortexar_reg_write(target_s *const target, const uint32_t reg, con if (max < reg_width) return 0; /* Finally, copy the new register data in and return the width */ - memcpy(reg_ptr, data, reg_width); + memcpy_swap(reg_ptr, data, reg_width); return reg_width; } From 4f8ebed1b6f3d756d2bdcc85bacd1462aeb1bf0a Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Tue, 1 Apr 2025 18:31:45 +0800 Subject: [PATCH 16/27] work to remove swap32() Signed-off-by: Sean Cross --- src/include/buffer_utils.h | 9 +++ src/target/cortexar.c | 126 ++++++++++++++++++++++++++++++------- src/target/cortexar.h | 6 ++ src/target/ti_tms570.c | 3 +- 4 files changed, 119 insertions(+), 25 deletions(-) diff --git a/src/include/buffer_utils.h b/src/include/buffer_utils.h index ed79f88dba4..782b6f65266 100644 --- a/src/include/buffer_utils.h +++ b/src/include/buffer_utils.h @@ -89,6 +89,15 @@ static inline uint64_t read_be8(const uint8_t *const buffer, const size_t offset ((uint64_t)data[6] << 8U) | data[7]; } +static inline uint64_t read_le8(const uint8_t *const buffer, const size_t offset) +{ + return ((uint64_t)buffer[offset + 7] << 56U) | ((uint64_t)buffer[offset + 6] << 48U) | + ((uint64_t)buffer[offset + 5] << 40U) | ((uint64_t)buffer[offset + 4] << 32U) | + ((uint64_t)buffer[offset + 3] << 24U) | ((uint64_t)buffer[offset + 2] << 16U) | + ((uint64_t)buffer[offset + 1] << 8U) | buffer[offset + 0]; +} + + static inline size_t write_char(char *const buffer, const size_t buffer_size, const size_t offset, const char c) { if (buffer && offset < buffer_size) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index ad620862dff..d1d9da6fa4b 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -59,11 +59,6 @@ #include -static uint32_t swap32(const uint32_t value) -{ - return ((value >> 24) & 0xff) | ((value >> 8) & 0xff00) | ((value << 8) & 0xff0000) | ((value << 24) & 0xff000000); -} - static void memcpy_swap(void *dest_v, const void *src_v, size_t count) { uint8_t *dest = dest_v; const uint8_t *src = src_v; @@ -357,11 +352,6 @@ static const uint16_t cortexar_spsr_encodings[5] = { #define CORTEXAR_MMFR0_VMSA_MASK 0x0000000fU #define CORTEXAR_MMFR0_PMSA_MASK 0x000000f0U -#define TOPT_FLAVOUR_FLOAT (1U << 1U) /* If set, core has a hardware FPU */ -#define TOPT_FLAVOUR_SEC_EXT (1U << 2U) /* If set, core has security extensions */ -#define TOPT_FLAVOUR_VIRT_EXT (1U << 3U) /* If set, core has virtualisation extensions */ -#define TOPT_FLAVOUR_VIRT_MEM (1U << 4U) /* If set, core uses the virtual memory model, not protected */ - #define CORTEXAR_STATUS_DATA_FAULT (1U << 0U) #define CORTEXAR_STATUS_MMU_FAULT (1U << 1U) #define CORTEXAR_STATUS_FAULT_CACHE_VALID (1U << 2U) @@ -1017,6 +1007,33 @@ static bool cortexar_check_error(target_s *const target) return fault || cortex_check_error(target); } + +static inline uint32_t cortexar_endian_dp_read(target_s *const target, const uint16_t addr) { + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; + uint32_t value = adiv5_dp_read(priv->base.ap->dp, addr); + if (target->target_options & TOPT_FLAVOUR_BE) { + uint8_t tmp_value[4]; + // The instruction run gave us back a value that we interpreted as little endian, however + write_le4(tmp_value, 0, value); + // This target is big endian, so convert to the opposite representation + value = read_be4(tmp_value, 0); + } + return value; +} + +static inline void cortexar_endian_dp_write(target_s *const target, const uint16_t addr, uint32_t value) { + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; + + if (target->target_options & TOPT_FLAVOUR_BE) { + uint8_t tmp_value[4]; + // The instruction run gave us back a value that we interpreted as little endian, however + write_le4(tmp_value, 0, value); + // This target is big endian, so convert to the opposite representation + value = read_be4(tmp_value, 0); + } + adiv5_dp_write(priv->base.ap->dp, addr, value); +} + /* Fast path for cortexar_mem_read(). Assumes the address to read data from is already loaded in r0. */ static inline bool cortexar_mem_read_fast(target_s *const target, uint32_t *const dest, const size_t count) { @@ -1034,7 +1051,7 @@ static inline bool cortexar_mem_read_fast(target_s *const target, uint32_t *cons /* Run the transfer, hammering the DTR */ for (size_t offset = 0; offset < count; ++offset) { /* Read the next value, which is the value for the last instruction run */ - const uint32_t value = swap32(adiv5_dp_read(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DTRRX))); + const uint32_t value = cortexar_endian_dp_read(target, ADIV5_AP_DB(CORTEXAR_BANKED_DTRRX)); /* If we've run the instruction at least once, store it */ if (offset) dest[offset - 1U] = value; @@ -1044,7 +1061,7 @@ static inline bool cortexar_mem_read_fast(target_s *const target, uint32_t *cons /* Go back into DCC Normal (Non-blocking) mode */ adiv5_dp_write(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DCSR), dbg_dcsr | CORTEXAR_DBG_DCSR_DCC_NORMAL); /* Grab the value of the last instruction run now it won't run again */ - dest[count - 1U] = swap32(adiv5_dp_read(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DTRRX))); + dest[count - 1U] = cortexar_endian_dp_read(target, ADIV5_AP_DB(CORTEXAR_BANKED_DTRRX)); /* Check if the instruction triggered a synchronous data abort */ return cortexar_check_data_abort(target, status); } @@ -1053,7 +1070,13 @@ static inline bool cortexar_mem_read_fast(target_s *const target, uint32_t *cons for (size_t offset = 0; offset < count; ++offset) { if (!cortexar_run_read_insn(target, ARM_LDC_R0_POSTINC4_DTRTX_INSN, dest + offset)) return false; /* Propagate failure if it happens */ - dest[offset] = swap32(dest[offset]); + if (target->target_options & TOPT_FLAVOUR_BE) { + uint8_t value[4]; + // The instruction run gave us back a value that we interpreted as little endian, however + write_le4(value, 0, dest[offset]); + // This target is big endian, so convert to the opposite representation + dest[offset] = read_be4(value, 0); + } } return true; /* Signal success */ } @@ -1179,7 +1202,7 @@ static inline bool cortexar_mem_write_fast(target_s *const target, const uint32_ adiv5_dp_write(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_ITR), ARM_STC_DTRRX_R0_POSTINC4_INSN); /* Run the transfer, hammering the DTR */ for (size_t offset = 0; offset < count; ++offset) - adiv5_dp_write(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DTRTX), swap32(src[offset])); + cortexar_endian_dp_write(target, ADIV5_AP_DB(CORTEXAR_BANKED_DTRTX), src[offset]); /* Now read out the status from the DCSR in case anything went wrong */ const uint32_t status = adiv5_dp_read(priv->base.ap->dp, ADIV5_AP_DB(CORTEXAR_BANKED_DCSR)); /* Go back into DCC Normal (Non-blocking) mode */ @@ -1190,7 +1213,13 @@ static inline bool cortexar_mem_write_fast(target_s *const target, const uint32_ /* Write each of the uint32_t's checking for failure */ for (size_t offset = 0; offset < count; ++offset) { - if (!cortexar_run_write_insn(target, ARM_STC_DTRRX_R0_POSTINC4_INSN, swap32(src[offset]))) + uint32_t value; + if (target->target_options & TOPT_FLAVOUR_BE) { + value = read_be4((const void *const)src, offset); + } else { + value = read_le4((const void *const)src, offset); + } + if (!cortexar_run_write_insn(target, ARM_STC_DTRRX_R0_POSTINC4_INSN, value)) return false; /* Propagate failure if it happens */ } return true; /* Signal success */ @@ -1291,11 +1320,29 @@ static void cortexar_regs_read(target_s *const target, void *const data) const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; uint32_t *const regs = (uint32_t *)data; /* Copy the register values out from our cache */ - memcpy_swap(regs, priv->core_regs.r, sizeof(priv->core_regs.r)); - regs[CORTEX_REG_CPSR] = swap32(priv->core_regs.cpsr); + for (size_t reg_index = 0; reg_index < sizeof(priv->core_regs.r) / sizeof(*priv->core_regs.r); reg_index++) + if (target->target_options & TOPT_FLAVOUR_BE) + write_be4(data, reg_index * 4, priv->core_regs.r[reg_index]); + else + write_le4(data, reg_index * 4, priv->core_regs.r[reg_index]); + if (target->target_options & TOPT_FLAVOUR_BE) { + uint8_t value[4]; + write_le4(value, 0, priv->core_regs.cpsr); + regs[CORTEX_REG_CPSR] = read_be4(value, 0); + } else + regs[CORTEX_REG_CPSR] = priv->core_regs.cpsr; if (target->target_options & TOPT_FLAVOUR_FLOAT) { - memcpy_swap(regs + CORTEXAR_GENERAL_REG_COUNT, priv->core_regs.d, sizeof(priv->core_regs.d)); - regs[CORTEX_REG_FPCSR] = swap32(priv->core_regs.fpcsr); + for (size_t reg_index = 0; reg_index < sizeof(priv->core_regs.d) / sizeof(*priv->core_regs.d); reg_index++) + if (target->target_options & TOPT_FLAVOUR_BE) + write_be4(data, (CORTEXAR_GENERAL_REG_COUNT + reg_index) * 4, priv->core_regs.d[reg_index]); + else + write_le4(data, (CORTEXAR_GENERAL_REG_COUNT + reg_index) * 4, priv->core_regs.d[reg_index]); + if (target->target_options & TOPT_FLAVOUR_BE) { + uint8_t value[4]; + write_le4(value, 0, priv->core_regs.fpcsr); + regs[CORTEX_REG_FPCSR] = read_be4(value, 0); + } else + regs[CORTEX_REG_FPCSR] = priv->core_regs.fpcsr; } } @@ -1304,11 +1351,29 @@ static void cortexar_regs_write(target_s *const target, const void *const data) cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; const uint32_t *const regs = (const uint32_t *)data; /* Copy the new register values into our cache */ - memcpy_swap(priv->core_regs.r, regs, sizeof(priv->core_regs.r)); - priv->core_regs.cpsr = swap32(regs[CORTEX_REG_CPSR]); + for (size_t reg_index = 0; reg_index < sizeof(priv->core_regs.r) / sizeof(*priv->core_regs.r); reg_index++) + if (target->target_options & TOPT_FLAVOUR_BE) + priv->core_regs.r[reg_index] = read_be4(data, reg_index * 4); + else + priv->core_regs.r[reg_index] = read_le4(data, reg_index * 4); + if (target->target_options & TOPT_FLAVOUR_BE) { + uint8_t value[4]; + write_le4(value, 0, regs[CORTEX_REG_CPSR]); + priv->core_regs.cpsr = read_be4(value, 0); + } else + priv->core_regs.cpsr = regs[CORTEX_REG_CPSR]; if (target->target_options & TOPT_FLAVOUR_FLOAT) { - memcpy_swap(priv->core_regs.d, regs + CORTEXAR_GENERAL_REG_COUNT, sizeof(priv->core_regs.d)); - priv->core_regs.fpcsr = swap32(regs[CORTEX_REG_FPCSR]); + for (size_t reg_index = 0; reg_index < sizeof(priv->core_regs.r) / sizeof(*priv->core_regs.r); reg_index++) + if (target->target_options & TOPT_FLAVOUR_BE) + priv->core_regs.d[reg_index] = read_be4(data, (reg_index + CORTEXAR_GENERAL_REG_COUNT) * 4); + else + priv->core_regs.d[reg_index] = read_le4(data, (reg_index + CORTEXAR_GENERAL_REG_COUNT) * 4); + if (target->target_options & TOPT_FLAVOUR_BE) { + uint8_t value[4]; + write_le4(value, 0, regs[CORTEX_REG_FPCSR]); + priv->core_regs.fpcsr = read_be4(value, 0); + } else + priv->core_regs.fpcsr = regs[CORTEX_REG_FPCSR]; } } @@ -1353,7 +1418,20 @@ static size_t cortexar_reg_read(target_s *const target, const uint32_t reg, void if (max < reg_width) return 0; /* Finally, copy the register data out and return the width */ - memcpy_swap(data, reg_ptr, reg_width); + switch (reg_width) { + case 4: + if (target->target_options & TOPT_FLAVOUR_BE) + *(uint32_t *)data = read_be4(reg_ptr, 0); + else + *(uint32_t *)data = read_le4(reg_ptr, 0); + break; + case 8: + if (target->target_options & TOPT_FLAVOUR_BE) + *(uint64_t *)data = read_be8(reg_ptr, 0); + else + *(uint64_t *)data = read_le8(reg_ptr, 0); + break; + } return reg_width; } diff --git a/src/target/cortexar.h b/src/target/cortexar.h index 25551ce9b16..f37316f50d8 100644 --- a/src/target/cortexar.h +++ b/src/target/cortexar.h @@ -36,6 +36,12 @@ #include "general.h" +#define TOPT_FLAVOUR_FLOAT (1U << 1U) /* If set, core has a hardware FPU */ +#define TOPT_FLAVOUR_SEC_EXT (1U << 2U) /* If set, core has security extensions */ +#define TOPT_FLAVOUR_VIRT_EXT (1U << 3U) /* If set, core has virtualisation extensions */ +#define TOPT_FLAVOUR_VIRT_MEM (1U << 4U) /* If set, core uses the virtual memory model, not protected */ +#define TOPT_FLAVOUR_BE (1U << 5U) /* If set, core is big endian, not little endian */ + void cortexar_invalidate_all_caches(target_s *target); #endif /* TARGET_CORTEXAR_H */ diff --git a/src/target/ti_tms570.c b/src/target/ti_tms570.c index 1cbdc09d24c..0acd87be57f 100644 --- a/src/target/ti_tms570.c +++ b/src/target/ti_tms570.c @@ -23,7 +23,8 @@ bool ti_tms570_probe(target_s *const target) } target->driver = "TMS570"; + target->target_options |= TOPT_FLAVOUR_BE; target_add_ram32(target, TMS570_SRAM_BASE, TMS570_SRAM_SIZE); target_add_ram32(target, TMS570_SRAM_ECC_BASE, TMS570_SRAM_SIZE); return true; -} \ No newline at end of file +} From 7845af3938f5f89265c20465aa6e165901ef13d7 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Wed, 2 Apr 2025 18:11:07 +0800 Subject: [PATCH 17/27] cortexar: fully remove swap32 and memcpy Signed-off-by: Sean Cross --- src/include/buffer_utils.h | 24 ++++++++++++++ src/target/cortexar.c | 67 ++++++++++++++++++++++++++++---------- src/target/cortexar.h | 6 ---- src/target/ti_tms570.c | 1 - 4 files changed, 74 insertions(+), 24 deletions(-) diff --git a/src/include/buffer_utils.h b/src/include/buffer_utils.h index 782b6f65266..b6f913cfd27 100644 --- a/src/include/buffer_utils.h +++ b/src/include/buffer_utils.h @@ -59,6 +59,30 @@ static inline void write_be4(uint8_t *const buffer, const size_t offset, const u buffer[offset + 3U] = value & 0xffU; } +static inline void write_le8(uint8_t *const buffer, const size_t offset, const uint64_t value) +{ + buffer[offset + 0U] = value & 0xffU; + buffer[offset + 1U] = (value >> 8U) & 0xffU; + buffer[offset + 2U] = (value >> 16U) & 0xffU; + buffer[offset + 3U] = (value >> 24U) & 0xffU; + buffer[offset + 4U] = (value >> 32U) & 0xffU; + buffer[offset + 5U] = (value >> 40U) & 0xffU; + buffer[offset + 6U] = (value >> 48U) & 0xffU; + buffer[offset + 7U] = (value >> 56U) & 0xffU; +} + +static inline void write_be8(uint8_t *const buffer, const size_t offset, const uint64_t value) +{ + buffer[offset + 0U] = (value >> 56U) & 0xffU; + buffer[offset + 1U] = (value >> 48U) & 0xffU; + buffer[offset + 2U] = (value >> 40U) & 0xffU; + buffer[offset + 3U] = (value >> 32U) & 0xffU; + buffer[offset + 4U] = (value >> 24U) & 0xffU; + buffer[offset + 5U] = (value >> 16U) & 0xffU; + buffer[offset + 6U] = (value >> 8U) & 0xffU; + buffer[offset + 7U] = value & 0xffU; +} + static inline uint16_t read_le2(const uint8_t *const buffer, const size_t offset) { uint8_t data[2U]; diff --git a/src/target/cortexar.c b/src/target/cortexar.c index d1d9da6fa4b..60a2c86202c 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -59,14 +59,6 @@ #include -static void memcpy_swap(void *dest_v, const void *src_v, size_t count) { - uint8_t *dest = dest_v; - const uint8_t *src = src_v; - for (size_t i = 0; i < count; i += 1) { - dest[(i&~3)+(~i&3)] = src[i]; - } -} - typedef struct cortexar_priv { /* Base core information */ cortex_priv_s base; @@ -202,6 +194,7 @@ typedef struct cortexar_priv { #define CORTEXAR_CPSR_MODE_HYP 0x0000001aU #define CORTEXAR_CPSR_MODE_SYS 0x0000001fU #define CORTEXAR_CPSR_THUMB (1U << 5U) +#define CORTEXAR_CPSR_BE (1U << 9U) /* CPSR remap position for GDB XML mapping */ #define CORTEXAR_CPSR_GDB_REMAP_POS 25U @@ -352,6 +345,12 @@ static const uint16_t cortexar_spsr_encodings[5] = { #define CORTEXAR_MMFR0_VMSA_MASK 0x0000000fU #define CORTEXAR_MMFR0_PMSA_MASK 0x000000f0U +#define TOPT_FLAVOUR_FLOAT (1U << 1U) /* If set, core has a hardware FPU */ +#define TOPT_FLAVOUR_SEC_EXT (1U << 2U) /* If set, core has security extensions */ +#define TOPT_FLAVOUR_VIRT_EXT (1U << 3U) /* If set, core has virtualisation extensions */ +#define TOPT_FLAVOUR_VIRT_MEM (1U << 4U) /* If set, core uses the virtual memory model, not protected */ +#define TOPT_FLAVOUR_BE (1U << 5U) /* If set, core is big endian, not little endian */ + #define CORTEXAR_STATUS_DATA_FAULT (1U << 0U) #define CORTEXAR_STATUS_MMU_FAULT (1U << 1U) #define CORTEXAR_STATUS_FAULT_CACHE_VALID (1U << 2U) @@ -889,6 +888,17 @@ static target_s *cortexar_probe( } else target_check_error(target); + /* Read the CPSR to figure out if this target is big endian. This clobbers r0, so save + * r0 beforehand and restore it after the read is complete. + */ + uint32_t r0 = cortexar_core_reg_read(target, 0U); + cortexar_run_insn(target, ARM_MRS_R0_CPSR_INSN); + priv->core_regs.cpsr = cortexar_core_reg_read(target, 0U); + cortexar_core_reg_write(target, 0U, r0); + if (priv->core_regs.cpsr & CORTEXAR_CPSR_BE) { + target->target_options |= TOPT_FLAVOUR_BE; + } + return target; } @@ -1215,9 +1225,9 @@ static inline bool cortexar_mem_write_fast(target_s *const target, const uint32_ for (size_t offset = 0; offset < count; ++offset) { uint32_t value; if (target->target_options & TOPT_FLAVOUR_BE) { - value = read_be4((const void *const)src, offset); + value = read_be4((const void *const)src, offset * 4); } else { - value = read_le4((const void *const)src, offset); + value = read_le4((const void *const)src, offset * 4); } if (!cortexar_run_write_insn(target, ARM_STC_DTRRX_R0_POSTINC4_INSN, value)) return false; /* Propagate failure if it happens */ @@ -1419,18 +1429,24 @@ static size_t cortexar_reg_read(target_s *const target, const uint32_t reg, void return 0; /* Finally, copy the register data out and return the width */ switch (reg_width) { - case 4: + case 4: { + uint32_t value; if (target->target_options & TOPT_FLAVOUR_BE) - *(uint32_t *)data = read_be4(reg_ptr, 0); + value = read_be4(reg_ptr, 0); else - *(uint32_t *)data = read_le4(reg_ptr, 0); + value = read_le4(reg_ptr, 0); + write_le4(data, 0, value); break; - case 8: + } + case 8: { + uint64_t value; if (target->target_options & TOPT_FLAVOUR_BE) - *(uint64_t *)data = read_be8(reg_ptr, 0); + value = read_be8(reg_ptr, 0); else - *(uint64_t *)data = read_le8(reg_ptr, 0); + value = read_le8(reg_ptr, 0); + write_le4(data, 0, value); break; + } } return reg_width; } @@ -1446,7 +1462,24 @@ static size_t cortexar_reg_write(target_s *const target, const uint32_t reg, con if (max < reg_width) return 0; /* Finally, copy the new register data in and return the width */ - memcpy_swap(reg_ptr, data, reg_width); + switch (reg_width) { + case 4: { + uint32_t value = read_le4(data, 0); + if (target->target_options & TOPT_FLAVOUR_BE) { + write_be4(reg_ptr, 0, value); + } else + write_le4(reg_ptr, 0, value); + break; + } + case 8: { + uint64_t value = read_le8(data, 0); + if (target->target_options & TOPT_FLAVOUR_BE) + write_be8(reg_ptr, 0, value); + else + write_le8(reg_ptr, 0, value); + break; + } + } return reg_width; } diff --git a/src/target/cortexar.h b/src/target/cortexar.h index f37316f50d8..25551ce9b16 100644 --- a/src/target/cortexar.h +++ b/src/target/cortexar.h @@ -36,12 +36,6 @@ #include "general.h" -#define TOPT_FLAVOUR_FLOAT (1U << 1U) /* If set, core has a hardware FPU */ -#define TOPT_FLAVOUR_SEC_EXT (1U << 2U) /* If set, core has security extensions */ -#define TOPT_FLAVOUR_VIRT_EXT (1U << 3U) /* If set, core has virtualisation extensions */ -#define TOPT_FLAVOUR_VIRT_MEM (1U << 4U) /* If set, core uses the virtual memory model, not protected */ -#define TOPT_FLAVOUR_BE (1U << 5U) /* If set, core is big endian, not little endian */ - void cortexar_invalidate_all_caches(target_s *target); #endif /* TARGET_CORTEXAR_H */ diff --git a/src/target/ti_tms570.c b/src/target/ti_tms570.c index 0acd87be57f..6e795418b04 100644 --- a/src/target/ti_tms570.c +++ b/src/target/ti_tms570.c @@ -23,7 +23,6 @@ bool ti_tms570_probe(target_s *const target) } target->driver = "TMS570"; - target->target_options |= TOPT_FLAVOUR_BE; target_add_ram32(target, TMS570_SRAM_BASE, TMS570_SRAM_SIZE); target_add_ram32(target, TMS570_SRAM_ECC_BASE, TMS570_SRAM_SIZE); return true; From 9e65c1e12c62abbbbe8172e521238f11797b82f3 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Wed, 2 Apr 2025 18:23:24 +0800 Subject: [PATCH 18/27] tms570: swap check word since this target is BE Since we don't swap everything now, the hardcoded check value needs to be swapped in order to properly read the value. Signed-off-by: Sean Cross --- src/target/ti_tms570.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/target/ti_tms570.c b/src/target/ti_tms570.c index 6e795418b04..0b87dde25bc 100644 --- a/src/target/ti_tms570.c +++ b/src/target/ti_tms570.c @@ -5,8 +5,8 @@ #define TMS570_SYS_BASE 0xffffff00U #define TMS570_SYS_DEVID (TMS570_SYS_BASE + 0xf0U) -#define TMS570_SCM_DEVID_ID_MASK 0x7ffe0007U -#define TMS570_SCM_REVID_ID_TMS570 0x00440005U +#define TMS570_SCM_DEVID_ID_MASK 0x0700fe7fU /* Note: value is swapped since target is BE */ +#define TMS570_SCM_REVID_ID_TMS570 0x05004400U /* Note: value is swapped since target is BE */ /* Base address for the OCRAM regions, including their mirrors (including RETRAM) */ #define TMS570_SRAM_BASE 0x08000000U @@ -19,8 +19,10 @@ bool ti_tms570_probe(target_s *const target) { const uint32_t part_id = target_mem32_read32(target, TMS570_SYS_DEVID); if (!part_id || ((part_id & TMS570_SCM_DEVID_ID_MASK) != TMS570_SCM_REVID_ID_TMS570)) { + fprintf(stderr, "Part ID 0x%08x was unrecognized\n", part_id); return false; } + fprintf(stderr, "Part ID 0x%08x was recognized as a TMS570\n", part_id); target->driver = "TMS570"; target_add_ram32(target, TMS570_SRAM_BASE, TMS570_SRAM_SIZE); From ad6a8ff26d4fae38716c34ed106f9fde85ee53d5 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Thu, 3 Apr 2025 16:45:05 +0800 Subject: [PATCH 19/27] incorporate feedback on patch-in-progress Signed-off-by: Sean Cross --- src/include/buffer_utils.h | 1 - src/target/cortexar.c | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/include/buffer_utils.h b/src/include/buffer_utils.h index b6f913cfd27..275e592395c 100644 --- a/src/include/buffer_utils.h +++ b/src/include/buffer_utils.h @@ -121,7 +121,6 @@ static inline uint64_t read_le8(const uint8_t *const buffer, const size_t offset ((uint64_t)buffer[offset + 1] << 8U) | buffer[offset + 0]; } - static inline size_t write_char(char *const buffer, const size_t buffer_size, const size_t offset, const char c) { if (buffer && offset < buffer_size) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 60a2c86202c..673c91eab02 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -895,9 +895,8 @@ static target_s *cortexar_probe( cortexar_run_insn(target, ARM_MRS_R0_CPSR_INSN); priv->core_regs.cpsr = cortexar_core_reg_read(target, 0U); cortexar_core_reg_write(target, 0U, r0); - if (priv->core_regs.cpsr & CORTEXAR_CPSR_BE) { + if (priv->core_regs.cpsr & CORTEXAR_CPSR_BE) target->target_options |= TOPT_FLAVOUR_BE; - } return target; } @@ -935,9 +934,11 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre if (!target) return false; - // TI omitted the designer code on TMS570. - if (target->designer_code == 0) { - PROBE(ti_tms570_probe); + switch (target->designer_code) { + /* TI omitted the designer code on TMS570 */ + case 0: + PROBE(ti_tms570_probe); + break; } #if CONFIG_BMDA == 0 @@ -1224,11 +1225,10 @@ static inline bool cortexar_mem_write_fast(target_s *const target, const uint32_ /* Write each of the uint32_t's checking for failure */ for (size_t offset = 0; offset < count; ++offset) { uint32_t value; - if (target->target_options & TOPT_FLAVOUR_BE) { - value = read_be4((const void *const)src, offset * 4); - } else { - value = read_le4((const void *const)src, offset * 4); - } + if (target->target_options & TOPT_FLAVOUR_BE) + value = read_be4((const void *)src, offset * 4U); + else + value = read_le4((const void *)src, offset * 4U); if (!cortexar_run_write_insn(target, ARM_STC_DTRRX_R0_POSTINC4_INSN, value)) return false; /* Propagate failure if it happens */ } @@ -1444,7 +1444,7 @@ static size_t cortexar_reg_read(target_s *const target, const uint32_t reg, void value = read_be8(reg_ptr, 0); else value = read_le8(reg_ptr, 0); - write_le4(data, 0, value); + write_le8(data, 0, value); break; } } From 6888a48eb3da2391d21302805858a8e8d8558f4b Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Tue, 15 Apr 2025 17:20:42 +0800 Subject: [PATCH 20/27] tms570: remove fprintf call This was used for debugging only. Signed-off-by: Sean Cross --- src/target/ti_tms570.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/ti_tms570.c b/src/target/ti_tms570.c index 0b87dde25bc..d54f29f45a3 100644 --- a/src/target/ti_tms570.c +++ b/src/target/ti_tms570.c @@ -19,13 +19,13 @@ bool ti_tms570_probe(target_s *const target) { const uint32_t part_id = target_mem32_read32(target, TMS570_SYS_DEVID); if (!part_id || ((part_id & TMS570_SCM_DEVID_ID_MASK) != TMS570_SCM_REVID_ID_TMS570)) { - fprintf(stderr, "Part ID 0x%08x was unrecognized\n", part_id); + DEBUG_ERROR("Part ID 0x%08"PRIx32" was unrecognized\n", part_id); return false; } - fprintf(stderr, "Part ID 0x%08x was recognized as a TMS570\n", part_id); target->driver = "TMS570"; target_add_ram32(target, TMS570_SRAM_BASE, TMS570_SRAM_SIZE); target_add_ram32(target, TMS570_SRAM_ECC_BASE, TMS570_SRAM_SIZE); + return true; } From 828ecc826de7ca5bb0cfb7c506a2b33a3fdeb92f Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Tue, 15 Apr 2025 17:26:06 +0800 Subject: [PATCH 21/27] fixup clang-formatting Signed-off-by: Sean Cross --- src/target/cortexar.c | 85 +++++++++++++++++++++--------------------- src/target/ti_tms570.c | 2 +- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 673c91eab02..0591d487468 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -935,10 +935,10 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre return false; switch (target->designer_code) { - /* TI omitted the designer code on TMS570 */ - case 0: - PROBE(ti_tms570_probe); - break; + /* TI omitted the designer code on TMS570 */ + case 0: + PROBE(ti_tms570_probe); + break; } #if CONFIG_BMDA == 0 @@ -1014,12 +1014,12 @@ static bool cortexar_check_error(target_s *const target) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; const bool fault = priv->core_status & (CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); - priv->core_status &= (uint8_t) ~(CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); + priv->core_status &= (uint8_t)~(CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); return fault || cortex_check_error(target); } - -static inline uint32_t cortexar_endian_dp_read(target_s *const target, const uint16_t addr) { +static inline uint32_t cortexar_endian_dp_read(target_s *const target, const uint16_t addr) +{ cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; uint32_t value = adiv5_dp_read(priv->base.ap->dp, addr); if (target->target_options & TOPT_FLAVOUR_BE) { @@ -1032,7 +1032,8 @@ static inline uint32_t cortexar_endian_dp_read(target_s *const target, const uin return value; } -static inline void cortexar_endian_dp_write(target_s *const target, const uint16_t addr, uint32_t value) { +static inline void cortexar_endian_dp_write(target_s *const target, const uint16_t addr, uint32_t value) +{ cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; if (target->target_options & TOPT_FLAVOUR_BE) { @@ -1429,24 +1430,24 @@ static size_t cortexar_reg_read(target_s *const target, const uint32_t reg, void return 0; /* Finally, copy the register data out and return the width */ switch (reg_width) { - case 4: { - uint32_t value; - if (target->target_options & TOPT_FLAVOUR_BE) - value = read_be4(reg_ptr, 0); - else - value = read_le4(reg_ptr, 0); - write_le4(data, 0, value); - break; - } - case 8: { - uint64_t value; - if (target->target_options & TOPT_FLAVOUR_BE) - value = read_be8(reg_ptr, 0); - else - value = read_le8(reg_ptr, 0); - write_le8(data, 0, value); - break; - } + case 4: { + uint32_t value; + if (target->target_options & TOPT_FLAVOUR_BE) + value = read_be4(reg_ptr, 0); + else + value = read_le4(reg_ptr, 0); + write_le4(data, 0, value); + break; + } + case 8: { + uint64_t value; + if (target->target_options & TOPT_FLAVOUR_BE) + value = read_be8(reg_ptr, 0); + else + value = read_le8(reg_ptr, 0); + write_le8(data, 0, value); + break; + } } return reg_width; } @@ -1463,22 +1464,22 @@ static size_t cortexar_reg_write(target_s *const target, const uint32_t reg, con return 0; /* Finally, copy the new register data in and return the width */ switch (reg_width) { - case 4: { - uint32_t value = read_le4(data, 0); - if (target->target_options & TOPT_FLAVOUR_BE) { - write_be4(reg_ptr, 0, value); - } else - write_le4(reg_ptr, 0, value); - break; - } - case 8: { - uint64_t value = read_le8(data, 0); - if (target->target_options & TOPT_FLAVOUR_BE) - write_be8(reg_ptr, 0, value); - else - write_le8(reg_ptr, 0, value); - break; - } + case 4: { + uint32_t value = read_le4(data, 0); + if (target->target_options & TOPT_FLAVOUR_BE) { + write_be4(reg_ptr, 0, value); + } else + write_le4(reg_ptr, 0, value); + break; + } + case 8: { + uint64_t value = read_le8(data, 0); + if (target->target_options & TOPT_FLAVOUR_BE) + write_be8(reg_ptr, 0, value); + else + write_le8(reg_ptr, 0, value); + break; + } } return reg_width; } diff --git a/src/target/ti_tms570.c b/src/target/ti_tms570.c index d54f29f45a3..cd005640cfc 100644 --- a/src/target/ti_tms570.c +++ b/src/target/ti_tms570.c @@ -19,7 +19,7 @@ bool ti_tms570_probe(target_s *const target) { const uint32_t part_id = target_mem32_read32(target, TMS570_SYS_DEVID); if (!part_id || ((part_id & TMS570_SCM_DEVID_ID_MASK) != TMS570_SCM_REVID_ID_TMS570)) { - DEBUG_ERROR("Part ID 0x%08"PRIx32" was unrecognized\n", part_id); + DEBUG_ERROR("Part ID 0x%08" PRIx32 " was unrecognized\n", part_id); return false; } From 514b5e08bb0e57c75f56777d51451a37537d7dcb Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Tue, 15 Apr 2025 17:34:17 +0800 Subject: [PATCH 22/27] manually fix formatting errors Signed-off-by: Sean Cross --- src/target/cortexar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 0591d487468..abfe5909980 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -250,7 +250,7 @@ static const uint16_t cortexar_spsr_encodings[5] = { (((opc1) << 21U) | ((crn) << 16U) | ((rt) << 12U) | ((coproc) << 8U) | ((opc2) << 5U) | (crm)) /* Packs a CRn and CRm value for the coprocessor IO routines below to unpack */ #define ENCODE_CP_REG(n, m, opc1, opc2) \ - ((((n) & 0xfU) << 4U) | ((m) & 0xfU) | (((opc1) & 0x7U) << 8U) | (((opc2) & 0x7U) << 12U)) + ((((n)&0xfU) << 4U) | ((m)&0xfU) | (((opc1)&0x7U) << 8U) | (((opc2)&0x7U) << 12U)) /* * Instruction encodings for coprocessor load/store @@ -1014,7 +1014,7 @@ static bool cortexar_check_error(target_s *const target) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; const bool fault = priv->core_status & (CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); - priv->core_status &= (uint8_t)~(CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); + priv->core_status &= (uint8_t) ~(CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); return fault || cortex_check_error(target); } From 94ca0c7a2334afade7d8e162e3ff63e8bdb250c3 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Fri, 25 Apr 2025 23:49:42 +0800 Subject: [PATCH 23/27] tms570 wip: get init working Signed-off-by: Sean Cross --- src/target/cortexar.c | 2 +- src/target/target_internal.h | 1 + src/target/ti_tms570.c | 211 ++++++++++++++++++++++++++++++++++- 3 files changed, 210 insertions(+), 4 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index abfe5909980..31f22d8a3d8 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -968,7 +968,7 @@ bool cortexar_attach(target_s *const target) target_halt_reason_e reason = TARGET_HALT_RUNNING; while (!platform_timeout_is_expired(&timeout) && reason == TARGET_HALT_RUNNING) reason = target_halt_poll(target, NULL); - if (reason != TARGET_HALT_REQUEST) { + if ((reason != TARGET_HALT_REQUEST) && (reason != TARGET_HALT_BREAKPOINT)) { DEBUG_ERROR("Failed to halt the core\n"); return false; } diff --git a/src/target/target_internal.h b/src/target/target_internal.h index f93238e2a75..2a96b37d943 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -168,6 +168,7 @@ struct target { union { bool unsafe_enabled; bool ke04_mode; + bool tms570_flash_initialized; }; bool attached; diff --git a/src/target/ti_tms570.c b/src/target/ti_tms570.c index cd005640cfc..fbf6b5e1319 100644 --- a/src/target/ti_tms570.c +++ b/src/target/ti_tms570.c @@ -2,19 +2,54 @@ #include "target.h" #include "target_internal.h" #include "cortexar.h" +#include "buffer_utils.h" -#define TMS570_SYS_BASE 0xffffff00U -#define TMS570_SYS_DEVID (TMS570_SYS_BASE + 0xf0U) -#define TMS570_SCM_DEVID_ID_MASK 0x0700fe7fU /* Note: value is swapped since target is BE */ +#define TMS570_SYS_BASE 0xFFFFFF00U +#define TMS570_SYS_DEVID (TMS570_SYS_BASE + 0xF0U) +#define TMS570_SCM_DEVID_ID_MASK 0x0700FE7FU /* Note: value is swapped since target is BE */ #define TMS570_SCM_REVID_ID_TMS570 0x05004400U /* Note: value is swapped since target is BE */ +#define TMS570_OTP_BANK0_MEMORY_INFORMATION 0xF008015CU +#define TMS570_OTP_BANK0_MEMORY_SIZE_MASK 0xFFFFU + /* Base address for the OCRAM regions, including their mirrors (including RETRAM) */ #define TMS570_SRAM_BASE 0x08000000U #define TMS570_SRAM_ECC_BASE 0x08400000U #define TMS570_SRAM_SIZE 0x80000U +#define TMS570_FLASH_BASE_ADDR 0x00000000U +#define TMS570_FLASH_SECTOR_ADDR (TMS570_L2FMC_BASE_ADDR + 0x408U) +#define TMS570_FLASH_SECTOR_SIZE + +#define TMS570_L2FMC_BASE_ADDR 0xFFF87000U +#define TMS570_L2FMC_FSPRD_ADDR (TMS570_FLASH_BASE_ADDR + 0x4U) +#define TMS570_L2FMC_FMAC_ADDR (TMS570_FLASH_BASE_ADDR + 0x50U) +#define TMS570_L2FMC_FLOCK_ADDR (TMS570_FLASH_BASE_ADDR + 0x64U) /* Undocumented */ +#define TMS570_L2FMC_FVREADCT_ADDR (TMS570_FLASH_BASE_ADDR + 0x80U) /* Undocumented */ +#define TMS570_L2FMC_FVNVCT_ADDR (TMS570_FLASH_BASE_ADDR + 0x8CU) /* Undocumented */ +#define TMS570_L2FMC_FVPPCT_ADDR (TMS570_FLASH_BASE_ADDR + 0x90U) /* Undocumented */ +#define TMS570_L2FMC_FVWLCT_ADDR (TMS570_FLASH_BASE_ADDR + 0x94U) /* Undocumented */ +#define TMS570_L2FMC_FEFUSE_ADDR (TMS570_FLASH_BASE_ADDR + 0x98U) /* Undocumented */ +#define TMS570_L2FMC_FBSTROBES_ADDR (TMS570_FLASH_BASE_ADDR + 0x100U) /* Undocumented */ +#define TMS570_L2FMC_FPSTROBES_ADDR (TMS570_FLASH_BASE_ADDR + 0x104U) /* Undocumented */ +#define TMS570_L2FMC_FBMODE_ADDR (TMS570_FLASH_BASE_ADDR + 0x108U) /* Undocumented */ +#define TMS570_L2FMC_FTCR_ADDR (TMS570_FLASH_BASE_ADDR + 0x10CU) /* Undocumented */ +#define TMS570_L2FMC_FSM_WR_ENA_ADDR (TMS570_FLASH_BASE_ADDR + 0x288U) + #define TMS570_OTP_PACKAGE_AND_FLASH_MEMORY_SIZE 0xf008015cU +#define TMS570_OTP_BANK0_BASE 0xF0080000U +#define TMS570_FLASH_OTP_BASE (TMS570_OTP_BANK0_BASE + 0x170) + +/* + * Flash functions + */ +static bool tms570_flash_erase(target_flash_s *flash, target_addr_t addr, size_t len); +static bool tms570_flash_write(target_flash_s *flash, target_addr_t dest, const void *src, size_t len); +static bool tms570_flash_prepare(target_flash_s *flash); +static bool tms570_flash_done(target_flash_s *flash); +static bool tms570_flash_initialize(target_s *const target); + bool ti_tms570_probe(target_s *const target) { const uint32_t part_id = target_mem32_read32(target, TMS570_SYS_DEVID); @@ -27,5 +62,175 @@ bool ti_tms570_probe(target_s *const target) target_add_ram32(target, TMS570_SRAM_BASE, TMS570_SRAM_SIZE); target_add_ram32(target, TMS570_SRAM_ECC_BASE, TMS570_SRAM_SIZE); + // target_flash_s *flash = calloc(1, sizeof(*flash)); + // if (!flash) { /* calloc failed: heap exhaustion */ + // DEBUG_ERROR("calloc: failed in %s\n", __func__); + // return false; + // } + + tms570_flash_initialize(target); + + // flash->start = TMS570_FLASH_BASE_ADDR; + // flash->length = flash_size; + // flash->blocksize = TMS570_FLASH_SECTOR_SIZE; + // flash->writesize = CH579_FLASH_WRITE_SIZE; + // flash->erase = tms570_flash_erase; + // flash->write = tms570_flash_write; + // flash->prepare = tms570_flash_prepare; + // flash->done = tms570_flash_done; + // flash->erased = 0xffU; + // target_add_flash(target, flash); + + return true; +} + +static uint32_t accumulate(uint32_t arg, const uint32_t val) +{ + arg += (val & 0xffffU); + return (arg & 0xffffU) + (arg >> 16); +} + +/// The flash configuration data is burned into a special OTP block on the target. +/// This data is hashed with a Fletcher checksum, which has the nice property that +/// it can tell us if the endianness is backwards or if we're not talking to the +/// correct device. The checksum value is stored in the last word of the OTP area. +static bool fletcher_checksum(const uint32_t *const otp_data, const size_t otp_data_count, const uint32_t comparison) +{ + uint32_t check_low = 0xffffU; + uint32_t check_high = 0xffffU; + + for (size_t i = 0; i < otp_data_count; i++) { + uint32_t word = otp_data[i]; + // Accumulate low word + check_low = accumulate(check_low, word); + check_high = accumulate(check_high, check_low); + // Accumulate high word + check_low = accumulate(check_low, word >> 16); + check_high = accumulate(check_high, check_low); + } + + uint32_t result = (check_high << 16) | check_low; + DEBUG_TARGET("Comparing result %08" PRIx32 " to check value %08" PRIx32 "\n", result, comparison); + return comparison == result; +} + +static bool tms570_flash_initialize(target_s *const target) +{ + if (target->tms570_flash_initialized) + return true; + + // Read the OTP data out of flash. This is protected with a Fletcher checksum + uint32_t otp_data[12]; + for (int i = 0; i < 12; i++) { + const uint32_t value = target_mem32_read32(target, TMS570_FLASH_OTP_BASE + (i * 4)); + otp_data[i] = read_be4((const uint8_t *)&value, 0); + DEBUG_TARGET("Flash OTP[0x%08" PRIx32 "]: 0x%08" PRIx32 "\n", TMS570_FLASH_OTP_BASE + (i * 4), otp_data[i]); + } + if (!fletcher_checksum(otp_data, 11, otp_data[11])) { + return false; + } + + // Enable all three banks + uint32_t fmac = target_mem32_read32(target, TMS570_L2FMC_FMAC_ADDR); + target_mem32_write32(target, TMS570_L2FMC_FMAC_ADDR, fmac | 7); + + // Disable read margin control. + // (Note: previously this set RMBSEL first and then RM0/1, but do both in one write now) + target_mem32_write32(target, TMS570_L2FMC_FSPRD_ADDR, 0); + + // Disable the FSM + target_mem32_write32(target, TMS570_L2FMC_FSM_WR_ENA_ADDR, 0); + + // Copy some timing values from OTP + uint32_t unk_210 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x210); + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x210, (unk_210 & 0xffff0000) | (otp_data[0] >> 16)); + uint32_t unk_218 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x218); + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x218, (unk_218 & 0xffff0000) | (otp_data[0] & 0xffff)); + + // Set the 2nd nibble after the first write is completed + uint32_t unk_21c = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x21c); + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x21c, (unk_21c & 0xffff00f0) | (otp_data[1] & 0xff0f)); + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x21c, (unk_21c & 0xffff0000) | (otp_data[1] & 0xffff)); + + // ??? + uint8_t unk_214 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x214); + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x214, (unk_214 & 0xffff0fff) | (otp_data[3] & 0xf000)); + + // ??? + uint8_t unk_220 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x220); + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x220, (unk_220 & 0xffffff00) | ((otp_data[1] >> 24) & 0xff)); + + // ??? + uint32_t unk_224 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x224); + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x224, (unk_224 & 0xffffff00) | ((otp_data[2] >> 16) & 0xff)); + + // ??? + uint16_t unk_268 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x268); + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x268, (unk_268 & 0xfffff000) | (otp_data[5] & 0xfff)); + + // ??? + uint16_t unk_26c = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x26c); + target_mem32_write16( + target, TMS570_L2FMC_BASE_ADDR + 0x26c, (unk_26c & 0xfe00ffff) | ((otp_data[8] & 0x1ff) << 16)); + + // NOTE: This used to be a 16-bit access -- ensure that it's properly swapped + uint16_t unk_270 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x270); + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x270, unk_270 & 0xfe00ffff); + + uint32_t unk_278 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x278); + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x278, (unk_278 & 0xffffff80) | ((otp_data[4] - 1) & 0x7f)); + + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x27c, 0x4500); + + // Unlock L2FMC + target_mem32_write32(target, TMS570_L2FMC_FLOCK_ADDR, 0x55aa); + + uint32_t fvreadct = target_mem32_read32(target, TMS570_L2FMC_FVREADCT_ADDR); + target_mem32_write32(target, TMS570_L2FMC_FVREADCT_ADDR, (fvreadct & 0xfffffff0) | ((otp_data[10] >> 8) & 0xf)); + + target_mem32_write32(target, TMS570_L2FMC_FVNVCT_ADDR, 0); + + target_mem32_write32(target, TMS570_L2FMC_FBSTROBES_ADDR, 0x00010104); + target_mem32_write32(target, TMS570_L2FMC_FPSTROBES_ADDR, 0x103); + target_mem32_write32(target, TMS570_L2FMC_FBMODE_ADDR, 0); + + uint32_t ftcr = target_mem32_read32(target, TMS570_L2FMC_FTCR_ADDR); + target_mem32_write32(target, TMS570_L2FMC_FTCR_ADDR, ftcr & 0xffffff80); + + uint32_t fvppct = target_mem32_read32(target, TMS570_L2FMC_FVPPCT_ADDR); + target_mem32_write32(target, TMS570_L2FMC_FVPPCT_ADDR, + (fvppct & 0xffffe0e0) | (((otp_data[9] >> 8) & 0x1f) << 8) | (otp_data[9] & 0x1f)); + + uint8_t fvwlct = target_mem32_read32(target, TMS570_L2FMC_FVWLCT_ADDR); + target_mem32_write32(target, TMS570_L2FMC_FVWLCT_ADDR, (fvwlct & ~0xf000) | ((otp_data[10] >> 24) & 0xf) << 12); + + uint32_t fefuse = target_mem32_read32(target, TMS570_L2FMC_FEFUSE_ADDR); + target_mem32_write32(target, TMS570_L2FMC_FEFUSE_ADDR, (fefuse & 0xffffffe0) | ((otp_data[10] >> 16) & 0x1f)); + + uint32_t unk_a8 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x0a8); + target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x0a8, (unk_a8 & 0xffffff00) | ((otp_data[3] >> 16) & 0xff)); + + target_mem32_write32(target, TMS570_L2FMC_FPSTROBES_ADDR, 0x103); + + target_mem32_write32(target, TMS570_L2FMC_FBSTROBES_ADDR, 0x10104); + + // Reads as 0x55aa + target_mem32_write32(target, TMS570_L2FMC_FLOCK_ADDR, 0); + + // Re-enable the FSM + uint32_t fsm = target_mem32_read32(target, TMS570_L2FMC_FSM_WR_ENA_ADDR); + target_mem32_write32(target, TMS570_L2FMC_FSM_WR_ENA_ADDR, (fsm & 0xfffffff8) | 2); + + target->tms570_flash_initialized = true; return true; } + +static bool tms570_flash_prepare(target_flash_s *flash) +{ + target_s *const target = flash->t; + + if (!tms570_flash_initialize(target)) { + DEBUG_ERROR("Checksum for OTP values doesn't match!"); + return false; + } +} From cf0960e643fb718be9096b25e4ec43661baa918d Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Tue, 3 Jun 2025 21:02:51 +0800 Subject: [PATCH 24/27] hosted: assert ntrst as part of connecting Assert the nTRST when connecting via JTAG. This is required for targets that use this pin to enable the JTAG circuitry. Signed-off-by: Sean Cross --- src/platforms/hosted/dap.c | 28 ++++++++++++++++++++++++++++ src/platforms/hosted/dap.h | 2 ++ src/platforms/hosted/dap_jtag.c | 2 ++ 3 files changed, 32 insertions(+) diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index bcb92692ebd..a092abdeae8 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -84,6 +84,7 @@ static bool dap_transfer_configure(uint8_t idle_cycles, uint16_t wait_retries, u static uint32_t dap_current_clock_freq; static bool dap_nrst_state = false; +static bool dap_ntrst_state = false; bool dap_connect(void) { @@ -236,6 +237,33 @@ bool dap_nrst_set_val(const bool nrst_state) return response == request.pin_values; } +bool dap_ntrst_get_val(void) +{ + return dap_ntrst_state; +} + +bool dap_ntrst_set_val(const bool ntrst_state) +{ + /* Setup the request for the pin state change request */ + dap_swj_pins_request_s request = { + .request = DAP_SWJ_PINS, + /* nRST is active low, so take that into account */ + .pin_values = ntrst_state ? 0U : DAP_SWJ_nTRST, + .selected_pins = DAP_SWJ_nTRST, + }; + /* Tell the hardware to wait for 10µs for the pin to settle */ + write_le4(request.wait_time, 0, 10); + uint8_t response = 0U; + /* Execute it and check if it failed */ + if (!dap_run_cmd(&request, 7U, &response, 1U)) { + DEBUG_PROBE("%s failed\n", __func__); + return false; + } + /* Extract the current pin state for the device, de-inverting it */ + dap_ntrst_state = !(response & DAP_SWJ_nTRST); + return response == request.pin_values; +} + uint32_t dap_read_reg(adiv5_debug_port_s *target_dp, const uint8_t reg) { const dap_transfer_request_s request = {.request = reg | DAP_TRANSFER_RnW}; diff --git a/src/platforms/hosted/dap.h b/src/platforms/hosted/dap.h index df6a7d6af05..05d6eaf4706 100644 --- a/src/platforms/hosted/dap.h +++ b/src/platforms/hosted/dap.h @@ -81,6 +81,8 @@ extern uint8_t dap_quirks; bool dap_connect(void); bool dap_disconnect(void); +bool dap_ntrst_get_val(void); +bool dap_ntrst_set_val(const bool ntrst_state); bool dap_led(dap_led_type_e type, bool state); size_t dap_info(dap_info_e requested_info, void *buffer, size_t buffer_length); bool dap_set_reset_state(bool nrst_state); diff --git a/src/platforms/hosted/dap_jtag.c b/src/platforms/hosted/dap_jtag.c index 9cc7e7b2e45..eabd68ab2c6 100644 --- a/src/platforms/hosted/dap_jtag.c +++ b/src/platforms/hosted/dap_jtag.c @@ -53,6 +53,8 @@ bool dap_jtag_init(void) dap_disconnect(); dap_mode = DAP_CAP_JTAG; dap_connect(); + dap_ntrst_set_val(true); + dap_ntrst_set_val(false); jtag_proc.jtagtap_reset = dap_jtag_reset; jtag_proc.jtagtap_next = dap_jtag_next; From fb65ae5baa8fedb1b1cab967a56dda1c465ca484 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Tue, 3 Jun 2025 21:02:51 +0800 Subject: [PATCH 25/27] jtag_scan: split out `jtag_discover()` This function will be used to re-discover JTAG devices without performing a JTAG reinit. Signed-off-by: Sean Cross --- src/include/target.h | 1 + src/target/jtag_scan.c | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/include/target.h b/src/include/target.h index 6f9151d3503..1e91205a0e3 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -55,6 +55,7 @@ bool bmda_rvswd_scan(void); bool adiv5_swd_scan(void); bool adiv5_swd_scan_targetid(uint32_t targetid); bool jtag_scan(void); +bool jtag_discover(void); bool onboard_flash_scan(void); size_t target_foreach(void (*callback)(size_t index, target_s *target, void *context), void *context); diff --git a/src/target/jtag_scan.c b/src/target/jtag_scan.c index eb70b50b4a5..61ce65f0462 100644 --- a/src/target/jtag_scan.c +++ b/src/target/jtag_scan.c @@ -76,12 +76,6 @@ void jtag_add_device(const uint32_t dev_index, const jtag_dev_s *jtag_dev) */ bool jtag_scan(void) { - /* Free the device list if any, and clean state ready */ - target_list_free(); - - jtag_dev_count = 0; - memset(&jtag_devs, 0, sizeof(jtag_devs)); - /* * Initialise the JTAG backend if it's not already * This will automatically do the SWD-to-JTAG sequence just in case we've got @@ -99,6 +93,17 @@ bool jtag_scan(void) /* Reset the chain ready */ jtag_proc.jtagtap_reset(); + return jtag_discover(); +} + +bool jtag_discover(void) +{ + /* Free the device list if any, and clean state ready */ + target_list_free(); + + jtag_dev_count = 0; + memset(&jtag_devs, 0, sizeof(jtag_devs)); + /* Start by reading out the ID Codes for all the devices on the chain */ if (!jtag_read_idcodes() || /* Otherwise, try and learn the chain IR lengths */ From fd8080cb32086ede59b3d71d63a1f4db8f828d81 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Tue, 3 Jun 2025 21:02:51 +0800 Subject: [PATCH 26/27] rtt: get working with big endian --- src/command.c | 14 ++++++++++ src/include/target.h | 2 ++ src/rtt.c | 50 +++++++++++++++++++++++++---------- src/target/cortexar.c | 51 ++++++++++++++++++++++-------------- src/target/jtag_scan.c | 9 ++++++- src/target/target.c | 30 ++++++++++++++++----- src/target/ti_tms570.c | 59 ++++++++++++++++-------------------------- 7 files changed, 139 insertions(+), 76 deletions(-) diff --git a/src/command.c b/src/command.c index c86dedb34f7..e72c03342ab 100644 --- a/src/command.c +++ b/src/command.c @@ -117,6 +117,7 @@ const command_s cmd_list[] = { {"halt_timeout", cmd_halt_timeout, "Timeout to wait until Cortex-M is halted: [TIMEOUT, default 2000ms]"}, {"connect_rst", cmd_connect_reset, "Configure connect under reset: [enable|disable]"}, {"reset", cmd_reset, "Pulse the nRST line - disconnects target: [PULSE_LEN, default 0ms]"}, + {"reset_halt", cmd_reset, "Reset the target and halt at the first instruction"}, {"tdi_low_reset", cmd_tdi_low_reset, "Pulse nRST with TDI set low to attempt to wake certain targets up (eg LPC82x)"}, #ifdef PLATFORM_HAS_POWER_SWITCH @@ -573,6 +574,19 @@ static bool cmd_halt_timeout(target_s *target, int argc, const char **argv) return true; } +static bool cmd_reset_halt(target_s *target, int argc, const char **argv) +{ + (void)target; + uint32_t pulse_len_ms = 0; + if (argc > 1) + pulse_len_ms = strtoul(argv[1], NULL, 0); + target_list_free(); + platform_nrst_set_val(true); + platform_delay(pulse_len_ms); + platform_nrst_set_val(false); + return true; +} + static bool cmd_reset(target_s *target, int argc, const char **argv) { (void)target; diff --git a/src/include/target.h b/src/include/target.h index 1e91205a0e3..192727671f4 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -72,8 +72,10 @@ void target_detach(target_s *target); /* Memory access functions */ bool target_mem_map(target_s *target, char *buf, size_t len); bool target_mem32_read(target_s *target, void *dest, target_addr_t src, size_t len); +bool target_mem32_read_unswapped(target_s *const target, void *const dest, const target_addr_t src, const size_t len); bool target_mem64_read(target_s *target, void *dest, target_addr64_t src, size_t len); bool target_mem32_write(target_s *target, target_addr_t dest, const void *src, size_t len); +bool target_mem32_write_unswapped(target_s *target, target_addr_t dest, const void *src, size_t len); bool target_mem64_write(target_s *target, target_addr64_t dest, const void *src, size_t len); bool target_mem_access_needs_halt(target_s *target); /* Flash memory access functions */ diff --git a/src/rtt.c b/src/rtt.c index d52f776753b..8c2bbe5838c 100644 --- a/src/rtt.c +++ b/src/rtt.c @@ -121,6 +121,7 @@ static char xmit_buf[RTT_UP_BUF_SIZE]; * [Algo] Rolling hash; Rabin-Karp string search * - 0: https://yurichev.com/news/20210205_rolling_hash/ */ + static uint32_t fast_search(target_s *const cur_target, const uint32_t ram_start, const uint32_t ram_end) { static const uint32_t hash_len = 16; @@ -140,12 +141,17 @@ static uint32_t fast_search(target_s *const cur_target, const uint32_t ram_start gdb_outf("rtt: read fail at 0x%" PRIx32 "\r\n", addr); return 0; } + fprintf(stderr, "RTT @ 0x%08x: ", addr); for (uint32_t i = 0; i < buf_siz; i++) { + fprintf(stderr, " %02x", srch_buf[i + hash_len]); hash = (hash + q - remainder * srch_buf[i] % q) % q; hash = ((hash << 8U) + srch_buf[i + hash_len]) % q; - if (pattern == hash) + if (pattern == hash) { + fprintf(stderr, "\n"); return addr + i - hash_len + 1U; + } } + fprintf(stderr, "\n"); } /* no match */ return 0; @@ -209,7 +215,7 @@ static void find_rtt(target_s *const cur_target) DEBUG_INFO("rtt: match at 0x%" PRIx32 "\n", rtt_cbaddr); /* read number of rtt up and down channels from target */ uint32_t num_buf[2]; - if (target_mem32_read(cur_target, num_buf, rtt_cbaddr + 16U, sizeof(num_buf))) + if (target_mem32_read_unswapped(cur_target, num_buf, rtt_cbaddr + 16U, sizeof(num_buf))) return; rtt_num_up_chan = num_buf[0]; if (rtt_num_up_chan > MAX_RTT_CHAN) @@ -233,6 +239,10 @@ static void find_rtt(target_s *const cur_target) /* clear channel data */ memset(rtt_channel, 0, sizeof rtt_channel); + /* save first 24 bytes of control block */ + if (target_mem32_read_unswapped(cur_target, saved_cblock_header, rtt_cbaddr, sizeof(saved_cblock_header))) + return; + /* auto channel: enable output channel 0, channel 1 and first input channel */ if (rtt_auto_channel) { for (uint32_t i = 0; i < MAX_RTT_CHAN; i++) @@ -243,12 +253,9 @@ static void find_rtt(target_s *const cur_target) rtt_channel_enabled[rtt_num_up_chan] = true; } - /* save first 24 bytes of control block */ - if (target_mem32_read(cur_target, saved_cblock_header, rtt_cbaddr, sizeof(saved_cblock_header))) - return; rtt_found = true; - DEBUG_INFO("rtt found\n"); + DEBUG_INFO("rtt found -- %d up channels and %d down channels\n", num_buf[0], num_buf[1]); } } @@ -276,8 +283,10 @@ static rtt_retval_e read_rtt(target_s *const cur_target, const uint32_t i) if (cur_target == NULL || rtt_channel[i].buf_addr == 0 || rtt_channel[i].buf_size == 0) return RTT_IDLE; - if (rtt_channel[i].head >= rtt_channel[i].buf_size || rtt_channel[i].tail >= rtt_channel[i].buf_size) + if (rtt_channel[i].head >= rtt_channel[i].buf_size || rtt_channel[i].tail >= rtt_channel[i].buf_size) { + DEBUG_TARGET("write head: %d buf_size: %d tail: %d\n", rtt_channel[i].head, rtt_channel[i].buf_size, rtt_channel[i].tail); return RTT_ERR; + } /* write recv_buf to target rtt 'down' buf */ while (true) { @@ -287,7 +296,7 @@ static rtt_retval_e read_rtt(target_s *const cur_target, const uint32_t i) const int ch = rtt_getchar(channel); if (ch == -1) break; - if (target_mem32_write(cur_target, rtt_channel[i].buf_addr + rtt_channel[i].head, &ch, 1)) + if (target_mem32_write_unswapped(cur_target, rtt_channel[i].buf_addr + rtt_channel[i].head, &ch, 1)) return RTT_ERR; /* advance head pointer */ rtt_channel[i].head = next_head; @@ -295,8 +304,10 @@ static rtt_retval_e read_rtt(target_s *const cur_target, const uint32_t i) /* update head of target 'down' buffer */ const uint32_t head_addr = rtt_cbaddr + 24U + i * 24U + 12U; - if (target_mem32_write(cur_target, head_addr, &rtt_channel[i].head, sizeof(rtt_channel[i].head))) + if (target_mem32_write_unswapped(cur_target, head_addr, &rtt_channel[i].head, sizeof(rtt_channel[i].head))) { + DEBUG_TARGET("Again with the write failure\n"); return RTT_ERR; + } return RTT_OK; } @@ -363,7 +374,7 @@ static rtt_retval_e print_rtt(target_s *const cur_target, const uint32_t i) /* update tail of target 'up' buffer */ const uint32_t tail_addr = rtt_cbaddr + 24U + i * 24U + 16U; - if (target_mem32_write(cur_target, tail_addr, &rtt_channel[i].tail, sizeof(rtt_channel[i].tail))) + if (target_mem32_write_unswapped(cur_target, tail_addr, &rtt_channel[i].tail, sizeof(rtt_channel[i].tail))) return RTT_ERR; /* write buffer to usb */ @@ -413,9 +424,22 @@ void poll_rtt(target_s *const cur_target) if (rtt_found) { uint32_t cblock_header[6]; // first 24 bytes of control block /* check control block not changed or corrupted */ - if (target_mem32_read(cur_target, cblock_header, rtt_cbaddr, sizeof(cblock_header)) || - memcmp(saved_cblock_header, cblock_header, sizeof(cblock_header)) != 0) + if (target_mem32_read_unswapped(cur_target, cblock_header, rtt_cbaddr, sizeof(cblock_header)) || + memcmp(saved_cblock_header, cblock_header, sizeof(cblock_header)) != 0) { + fprintf(stderr, "Read %lu blocks from 0x%08x and it's different\n", sizeof(cblock_header), rtt_cbaddr); + unsigned int i; + fprintf(stderr, "saved: "); + for (i = 0; i < sizeof(cblock_header)/4; i++) { + fprintf(stderr, " %08x", saved_cblock_header[i]); + } + fprintf(stderr, "\n"); + fprintf(stderr, "found: "); + for (i = 0; i < sizeof(cblock_header)/4; i++) { + fprintf(stderr, " %08x", cblock_header[i]); + } + fprintf(stderr, "\n"); rtt_found = false; // force searching control block next poll_rtt() + } } bool rtt_err = false; @@ -424,7 +448,7 @@ void poll_rtt(target_s *const cur_target) if (rtt_found && rtt_cbaddr) { /* copy control block from target */ uint32_t rtt_cblock_size = sizeof(rtt_channel[0]) * (rtt_num_up_chan + rtt_num_down_chan); - if (target_mem32_read(cur_target, rtt_channel, rtt_cbaddr + 24U, rtt_cblock_size)) { + if (target_mem32_read_unswapped(cur_target, rtt_channel, rtt_cbaddr + 24U, rtt_cblock_size)) { gdb_outf("rtt: read fail at 0x%" PRIx32 "\r\n", rtt_cbaddr + 24U); rtt_err = true; } else { diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 31f22d8a3d8..e2fb42e11d9 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -70,6 +70,8 @@ typedef struct cortexar_priv { uint32_t spsr[5U]; uint64_t d[16U]; uint32_t fpcsr; + uint32_t dfsr; + uint32_t dfar; } core_regs; /* Fault status/address cache */ @@ -701,7 +703,6 @@ static target_addr_t cortexar_virt_to_phys(target_s *const target, const target_ static bool cortexar_oslock_unlock(target_s *const target) { const uint32_t lock_status = cortex_dbg_read32(target, CORTEXAR_DBG_OSLSR); - DEBUG_TARGET("%s: OS lock status: %08" PRIx32 "\n", __func__, lock_status); /* Check if the lock is implemented, then if it is, if it's set */ if (((lock_status & CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL) == CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL_FULL || (lock_status & CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL) == CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL_PARTIAL) && @@ -1022,7 +1023,8 @@ static inline uint32_t cortexar_endian_dp_read(target_s *const target, const uin { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; uint32_t value = adiv5_dp_read(priv->base.ap->dp, addr); - if (target->target_options & TOPT_FLAVOUR_BE) { + extern bool skip_swap; + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) { uint8_t tmp_value[4]; // The instruction run gave us back a value that we interpreted as little endian, however write_le4(tmp_value, 0, value); @@ -1035,8 +1037,9 @@ static inline uint32_t cortexar_endian_dp_read(target_s *const target, const uin static inline void cortexar_endian_dp_write(target_s *const target, const uint16_t addr, uint32_t value) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; + extern bool skip_swap; - if (target->target_options & TOPT_FLAVOUR_BE) { + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) { uint8_t tmp_value[4]; // The instruction run gave us back a value that we interpreted as little endian, however write_le4(tmp_value, 0, value); @@ -1082,7 +1085,8 @@ static inline bool cortexar_mem_read_fast(target_s *const target, uint32_t *cons for (size_t offset = 0; offset < count; ++offset) { if (!cortexar_run_read_insn(target, ARM_LDC_R0_POSTINC4_DTRTX_INSN, dest + offset)) return false; /* Propagate failure if it happens */ - if (target->target_options & TOPT_FLAVOUR_BE) { + extern bool skip_swap; + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) { uint8_t value[4]; // The instruction run gave us back a value that we interpreted as little endian, however write_le4(value, 0, dest[offset]); @@ -1226,7 +1230,8 @@ static inline bool cortexar_mem_write_fast(target_s *const target, const uint32_ /* Write each of the uint32_t's checking for failure */ for (size_t offset = 0; offset < count; ++offset) { uint32_t value; - if (target->target_options & TOPT_FLAVOUR_BE) + extern bool skip_swap; + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) value = read_be4((const void *)src, offset * 4U); else value = read_le4((const void *)src, offset * 4U); @@ -1330,13 +1335,14 @@ static void cortexar_regs_read(target_s *const target, void *const data) { const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; uint32_t *const regs = (uint32_t *)data; + extern bool skip_swap; /* Copy the register values out from our cache */ for (size_t reg_index = 0; reg_index < sizeof(priv->core_regs.r) / sizeof(*priv->core_regs.r); reg_index++) - if (target->target_options & TOPT_FLAVOUR_BE) + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) write_be4(data, reg_index * 4, priv->core_regs.r[reg_index]); else write_le4(data, reg_index * 4, priv->core_regs.r[reg_index]); - if (target->target_options & TOPT_FLAVOUR_BE) { + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) { uint8_t value[4]; write_le4(value, 0, priv->core_regs.cpsr); regs[CORTEX_REG_CPSR] = read_be4(value, 0); @@ -1344,11 +1350,11 @@ static void cortexar_regs_read(target_s *const target, void *const data) regs[CORTEX_REG_CPSR] = priv->core_regs.cpsr; if (target->target_options & TOPT_FLAVOUR_FLOAT) { for (size_t reg_index = 0; reg_index < sizeof(priv->core_regs.d) / sizeof(*priv->core_regs.d); reg_index++) - if (target->target_options & TOPT_FLAVOUR_BE) + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) write_be4(data, (CORTEXAR_GENERAL_REG_COUNT + reg_index) * 4, priv->core_regs.d[reg_index]); else write_le4(data, (CORTEXAR_GENERAL_REG_COUNT + reg_index) * 4, priv->core_regs.d[reg_index]); - if (target->target_options & TOPT_FLAVOUR_BE) { + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) { uint8_t value[4]; write_le4(value, 0, priv->core_regs.fpcsr); regs[CORTEX_REG_FPCSR] = read_be4(value, 0); @@ -1361,13 +1367,14 @@ static void cortexar_regs_write(target_s *const target, const void *const data) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; const uint32_t *const regs = (const uint32_t *)data; + extern bool skip_swap; /* Copy the new register values into our cache */ for (size_t reg_index = 0; reg_index < sizeof(priv->core_regs.r) / sizeof(*priv->core_regs.r); reg_index++) - if (target->target_options & TOPT_FLAVOUR_BE) + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) priv->core_regs.r[reg_index] = read_be4(data, reg_index * 4); else priv->core_regs.r[reg_index] = read_le4(data, reg_index * 4); - if (target->target_options & TOPT_FLAVOUR_BE) { + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) { uint8_t value[4]; write_le4(value, 0, regs[CORTEX_REG_CPSR]); priv->core_regs.cpsr = read_be4(value, 0); @@ -1375,11 +1382,11 @@ static void cortexar_regs_write(target_s *const target, const void *const data) priv->core_regs.cpsr = regs[CORTEX_REG_CPSR]; if (target->target_options & TOPT_FLAVOUR_FLOAT) { for (size_t reg_index = 0; reg_index < sizeof(priv->core_regs.r) / sizeof(*priv->core_regs.r); reg_index++) - if (target->target_options & TOPT_FLAVOUR_BE) + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) priv->core_regs.d[reg_index] = read_be4(data, (reg_index + CORTEXAR_GENERAL_REG_COUNT) * 4); else priv->core_regs.d[reg_index] = read_le4(data, (reg_index + CORTEXAR_GENERAL_REG_COUNT) * 4); - if (target->target_options & TOPT_FLAVOUR_BE) { + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) { uint8_t value[4]; write_le4(value, 0, regs[CORTEX_REG_FPCSR]); priv->core_regs.fpcsr = read_be4(value, 0); @@ -1420,6 +1427,7 @@ static size_t cortexar_reg_width(const size_t reg) static size_t cortexar_reg_read(target_s *const target, const uint32_t reg, void *const data, const size_t max) { + extern bool skip_swap; /* Try to get a pointer to the storage for the requested register, and return -1 if that fails */ const void *const reg_ptr = cortexar_reg_ptr(target, reg); if (!reg_ptr) @@ -1432,7 +1440,7 @@ static size_t cortexar_reg_read(target_s *const target, const uint32_t reg, void switch (reg_width) { case 4: { uint32_t value; - if (target->target_options & TOPT_FLAVOUR_BE) + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) value = read_be4(reg_ptr, 0); else value = read_le4(reg_ptr, 0); @@ -1441,7 +1449,7 @@ static size_t cortexar_reg_read(target_s *const target, const uint32_t reg, void } case 8: { uint64_t value; - if (target->target_options & TOPT_FLAVOUR_BE) + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) value = read_be8(reg_ptr, 0); else value = read_le8(reg_ptr, 0); @@ -1454,6 +1462,7 @@ static size_t cortexar_reg_read(target_s *const target, const uint32_t reg, void static size_t cortexar_reg_write(target_s *const target, const uint32_t reg, const void *const data, const size_t max) { + extern bool skip_swap; /* Try to get a pointer to the storage for the requested register, and return -1 if that fails */ void *const reg_ptr = cortexar_reg_ptr(target, reg); if (!reg_ptr) @@ -1466,15 +1475,15 @@ static size_t cortexar_reg_write(target_s *const target, const uint32_t reg, con switch (reg_width) { case 4: { uint32_t value = read_le4(data, 0); - if (target->target_options & TOPT_FLAVOUR_BE) { + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) write_be4(reg_ptr, 0, value); - } else + else write_le4(reg_ptr, 0, value); break; } case 8: { uint64_t value = read_le8(data, 0); - if (target->target_options & TOPT_FLAVOUR_BE) + if ((target->target_options & TOPT_FLAVOUR_BE) && !skip_swap) write_be8(reg_ptr, 0, value); else write_le8(reg_ptr, 0, value); @@ -1520,7 +1529,7 @@ static void cortexar_reset(target_s *const target) #endif /* 10ms delay to ensure bootroms have had time to run */ - platform_delay(10); + // platform_delay(10); /* Ignore any initial errors out of reset */ target_check_error(target); } @@ -1628,6 +1637,10 @@ static void cortexar_halt_resume(target_s *const target, const bool step) /* Invalidate all the instruction caches if we're on a VMSA model device */ if (target->target_options & TOPT_FLAVOUR_VIRT_MEM) cortexar_coproc_write(target, CORTEXAR_ICIALLU, 0U); + else { + cortexar_coproc_write(target, CORTEXAR_ICIALLU, 0U); + // cortexar_run_insn(target, ARM_ISB_INSN); + } /* Mark the fault status and address cache invalid */ priv->core_status &= ~CORTEXAR_STATUS_FAULT_CACHE_VALID; diff --git a/src/target/jtag_scan.c b/src/target/jtag_scan.c index 61ce65f0462..8af28ec4651 100644 --- a/src/target/jtag_scan.c +++ b/src/target/jtag_scan.c @@ -216,7 +216,14 @@ static void jtag_display_idcodes(void) break; } } - DEBUG_INFO("ID code 0x%08" PRIx32 ": %s\n", jtag_devs[device].jd_idcode, description); + DEBUG_INFO("ID code 0x%08" PRIx32 ": %-20s | drpre: %d drpost: %d irpre: %d irpost: %d irlen: %d\n", + jtag_devs[device].jd_idcode, description, + jtag_devs[device].dr_prescan, + jtag_devs[device].dr_postscan, + jtag_devs[device].ir_prescan, + jtag_devs[device].ir_postscan, + jtag_devs[device].ir_len + ); } #endif } diff --git a/src/target/target.c b/src/target/target.c index b358f8d7090..6b8449aeecc 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -312,12 +312,23 @@ bool target_check_error(target_s *target) return false; } +bool skip_swap = false; + /* Memory access functions */ bool target_mem32_read(target_s *const target, void *const dest, const target_addr_t src, const size_t len) { return target_mem64_read(target, dest, src, len); } +/* Memory access functions */ +bool target_mem32_read_unswapped(target_s *const target, void *const dest, const target_addr_t src, const size_t len) +{ + skip_swap = true; + bool val = target_mem64_read(target, dest, src, len); + skip_swap = false; + return val; +} + bool target_mem64_read(target_s *const target, void *const dest, const target_addr64_t src, const size_t len) { /* If we're processing a semihosting syscall and it needs IO redirected, handle that instead */ @@ -339,6 +350,14 @@ bool target_mem32_write(target_s *const target, const target_addr_t dest, const return target_mem64_write(target, dest, src, len); } +bool target_mem32_write_unswapped(target_s *const target, const target_addr_t dest, const void *const src, const size_t len) +{ + skip_swap = true; + bool val = target_mem64_write(target, dest, src, len); + skip_swap = false; + return val; +} + bool target_mem64_write(target_s *const target, const target_addr64_t dest, const void *const src, const size_t len) { /* If we're processing a semihosting syscall and it needs IO redirected, handle that instead */ @@ -406,7 +425,6 @@ void target_reset(target_s *target) void target_halt_request(target_s *target) { - DEBUG_TARGET("Halting target\n"); if (target->halt_request) target->halt_request(target); } @@ -439,10 +457,10 @@ target_halt_reason_e target_halt_poll(target_s *target, target_addr64_t *watch) { if (target->halt_poll) { const target_halt_reason_e reason = target->halt_poll(target, watch); -#ifndef DEBUG_TARGET_IS_NOOP - if (reason != TARGET_HALT_RUNNING) - DEBUG_TARGET("Target halted: %s\n", target_halt_reason_str(reason)); -#endif +// #ifndef DEBUG_TARGET_IS_NOOP +// if (reason != TARGET_HALT_RUNNING) +// DEBUG_TARGET("Target halted: %s\n", target_halt_reason_str(reason)); +// #endif return reason; } /* XXX: Is this actually the desired fallback behaviour? */ @@ -451,7 +469,7 @@ target_halt_reason_e target_halt_poll(target_s *target, target_addr64_t *watch) void target_halt_resume(target_s *target, bool step) { - DEBUG_TARGET("%s target\n", step ? "Single stepping" : "Resuming"); + // DEBUG_TARGET("%s target\n", step ? "Single stepping" : "Resuming"); if (target->halt_resume) target->halt_resume(target, step); } diff --git a/src/target/ti_tms570.c b/src/target/ti_tms570.c index fbf6b5e1319..b59dbf544a0 100644 --- a/src/target/ti_tms570.c +++ b/src/target/ti_tms570.c @@ -62,24 +62,8 @@ bool ti_tms570_probe(target_s *const target) target_add_ram32(target, TMS570_SRAM_BASE, TMS570_SRAM_SIZE); target_add_ram32(target, TMS570_SRAM_ECC_BASE, TMS570_SRAM_SIZE); - // target_flash_s *flash = calloc(1, sizeof(*flash)); - // if (!flash) { /* calloc failed: heap exhaustion */ - // DEBUG_ERROR("calloc: failed in %s\n", __func__); - // return false; - // } - - tms570_flash_initialize(target); - - // flash->start = TMS570_FLASH_BASE_ADDR; - // flash->length = flash_size; - // flash->blocksize = TMS570_FLASH_SECTOR_SIZE; - // flash->writesize = CH579_FLASH_WRITE_SIZE; - // flash->erase = tms570_flash_erase; - // flash->write = tms570_flash_write; - // flash->prepare = tms570_flash_prepare; - // flash->done = tms570_flash_done; - // flash->erased = 0xffU; - // target_add_flash(target, flash); + // Avoid toggling NRST, which will reset the icepick. + target->target_options |= TOPT_INHIBIT_NRST; return true; } @@ -118,6 +102,7 @@ static bool tms570_flash_initialize(target_s *const target) { if (target->tms570_flash_initialized) return true; + DEBUG_TARGET("Initializing flash...\n"); // Read the OTP data out of flash. This is protected with a Fletcher checksum uint32_t otp_data[12]; @@ -131,7 +116,7 @@ static bool tms570_flash_initialize(target_s *const target) } // Enable all three banks - uint32_t fmac = target_mem32_read32(target, TMS570_L2FMC_FMAC_ADDR); + const uint32_t fmac = target_mem32_read32(target, TMS570_L2FMC_FMAC_ADDR); target_mem32_write32(target, TMS570_L2FMC_FMAC_ADDR, fmac | 7); // Disable read margin control. @@ -142,42 +127,42 @@ static bool tms570_flash_initialize(target_s *const target) target_mem32_write32(target, TMS570_L2FMC_FSM_WR_ENA_ADDR, 0); // Copy some timing values from OTP - uint32_t unk_210 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x210); + const uint32_t unk_210 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x210); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x210, (unk_210 & 0xffff0000) | (otp_data[0] >> 16)); - uint32_t unk_218 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x218); + const uint32_t unk_218 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x218); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x218, (unk_218 & 0xffff0000) | (otp_data[0] & 0xffff)); // Set the 2nd nibble after the first write is completed - uint32_t unk_21c = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x21c); + const uint32_t unk_21c = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x21c); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x21c, (unk_21c & 0xffff00f0) | (otp_data[1] & 0xff0f)); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x21c, (unk_21c & 0xffff0000) | (otp_data[1] & 0xffff)); // ??? - uint8_t unk_214 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x214); + const uint32_t unk_214 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x214); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x214, (unk_214 & 0xffff0fff) | (otp_data[3] & 0xf000)); // ??? - uint8_t unk_220 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x220); + const uint32_t unk_220 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x220); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x220, (unk_220 & 0xffffff00) | ((otp_data[1] >> 24) & 0xff)); // ??? - uint32_t unk_224 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x224); + const uint32_t unk_224 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x224); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x224, (unk_224 & 0xffffff00) | ((otp_data[2] >> 16) & 0xff)); // ??? - uint16_t unk_268 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x268); + const uint32_t unk_268 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x268); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x268, (unk_268 & 0xfffff000) | (otp_data[5] & 0xfff)); // ??? - uint16_t unk_26c = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x26c); + const uint32_t unk_26c = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x26c); target_mem32_write16( target, TMS570_L2FMC_BASE_ADDR + 0x26c, (unk_26c & 0xfe00ffff) | ((otp_data[8] & 0x1ff) << 16)); // NOTE: This used to be a 16-bit access -- ensure that it's properly swapped - uint16_t unk_270 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x270); + const uint32_t unk_270 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x270); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x270, unk_270 & 0xfe00ffff); - uint32_t unk_278 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x278); + const uint32_t unk_278 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x278); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x278, (unk_278 & 0xffffff80) | ((otp_data[4] - 1) & 0x7f)); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x27c, 0x4500); @@ -185,7 +170,7 @@ static bool tms570_flash_initialize(target_s *const target) // Unlock L2FMC target_mem32_write32(target, TMS570_L2FMC_FLOCK_ADDR, 0x55aa); - uint32_t fvreadct = target_mem32_read32(target, TMS570_L2FMC_FVREADCT_ADDR); + const uint32_t fvreadct = target_mem32_read32(target, TMS570_L2FMC_FVREADCT_ADDR); target_mem32_write32(target, TMS570_L2FMC_FVREADCT_ADDR, (fvreadct & 0xfffffff0) | ((otp_data[10] >> 8) & 0xf)); target_mem32_write32(target, TMS570_L2FMC_FVNVCT_ADDR, 0); @@ -194,20 +179,20 @@ static bool tms570_flash_initialize(target_s *const target) target_mem32_write32(target, TMS570_L2FMC_FPSTROBES_ADDR, 0x103); target_mem32_write32(target, TMS570_L2FMC_FBMODE_ADDR, 0); - uint32_t ftcr = target_mem32_read32(target, TMS570_L2FMC_FTCR_ADDR); + const uint32_t ftcr = target_mem32_read32(target, TMS570_L2FMC_FTCR_ADDR); target_mem32_write32(target, TMS570_L2FMC_FTCR_ADDR, ftcr & 0xffffff80); - uint32_t fvppct = target_mem32_read32(target, TMS570_L2FMC_FVPPCT_ADDR); + const uint32_t fvppct = target_mem32_read32(target, TMS570_L2FMC_FVPPCT_ADDR); target_mem32_write32(target, TMS570_L2FMC_FVPPCT_ADDR, (fvppct & 0xffffe0e0) | (((otp_data[9] >> 8) & 0x1f) << 8) | (otp_data[9] & 0x1f)); - uint8_t fvwlct = target_mem32_read32(target, TMS570_L2FMC_FVWLCT_ADDR); + const uint32_t fvwlct = target_mem32_read32(target, TMS570_L2FMC_FVWLCT_ADDR); target_mem32_write32(target, TMS570_L2FMC_FVWLCT_ADDR, (fvwlct & ~0xf000) | ((otp_data[10] >> 24) & 0xf) << 12); - uint32_t fefuse = target_mem32_read32(target, TMS570_L2FMC_FEFUSE_ADDR); + const uint32_t fefuse = target_mem32_read32(target, TMS570_L2FMC_FEFUSE_ADDR); target_mem32_write32(target, TMS570_L2FMC_FEFUSE_ADDR, (fefuse & 0xffffffe0) | ((otp_data[10] >> 16) & 0x1f)); - uint32_t unk_a8 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x0a8); + const uint32_t unk_a8 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x0a8); target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x0a8, (unk_a8 & 0xffffff00) | ((otp_data[3] >> 16) & 0xff)); target_mem32_write32(target, TMS570_L2FMC_FPSTROBES_ADDR, 0x103); @@ -218,7 +203,7 @@ static bool tms570_flash_initialize(target_s *const target) target_mem32_write32(target, TMS570_L2FMC_FLOCK_ADDR, 0); // Re-enable the FSM - uint32_t fsm = target_mem32_read32(target, TMS570_L2FMC_FSM_WR_ENA_ADDR); + const uint32_t fsm = target_mem32_read32(target, TMS570_L2FMC_FSM_WR_ENA_ADDR); target_mem32_write32(target, TMS570_L2FMC_FSM_WR_ENA_ADDR, (fsm & 0xfffffff8) | 2); target->tms570_flash_initialized = true; @@ -230,7 +215,7 @@ static bool tms570_flash_prepare(target_flash_s *flash) target_s *const target = flash->t; if (!tms570_flash_initialize(target)) { - DEBUG_ERROR("Checksum for OTP values doesn't match!"); + DEBUG_ERROR("Unable to initialize flash!"); return false; } } From 9351065c9bb64f3b4ee8f80df84b8d881e83d365 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sat, 11 Oct 2025 13:24:50 +0800 Subject: [PATCH 27/27] remove tms570 flash blocks since they do not work --- src/command.c | 13 ---- src/target/ti_tms570.c | 157 ----------------------------------------- 2 files changed, 170 deletions(-) diff --git a/src/command.c b/src/command.c index e72c03342ab..a2d997ca62e 100644 --- a/src/command.c +++ b/src/command.c @@ -574,19 +574,6 @@ static bool cmd_halt_timeout(target_s *target, int argc, const char **argv) return true; } -static bool cmd_reset_halt(target_s *target, int argc, const char **argv) -{ - (void)target; - uint32_t pulse_len_ms = 0; - if (argc > 1) - pulse_len_ms = strtoul(argv[1], NULL, 0); - target_list_free(); - platform_nrst_set_val(true); - platform_delay(pulse_len_ms); - platform_nrst_set_val(false); - return true; -} - static bool cmd_reset(target_s *target, int argc, const char **argv) { (void)target; diff --git a/src/target/ti_tms570.c b/src/target/ti_tms570.c index b59dbf544a0..7343cf1e811 100644 --- a/src/target/ti_tms570.c +++ b/src/target/ti_tms570.c @@ -44,11 +44,6 @@ /* * Flash functions */ -static bool tms570_flash_erase(target_flash_s *flash, target_addr_t addr, size_t len); -static bool tms570_flash_write(target_flash_s *flash, target_addr_t dest, const void *src, size_t len); -static bool tms570_flash_prepare(target_flash_s *flash); -static bool tms570_flash_done(target_flash_s *flash); -static bool tms570_flash_initialize(target_s *const target); bool ti_tms570_probe(target_s *const target) { @@ -67,155 +62,3 @@ bool ti_tms570_probe(target_s *const target) return true; } - -static uint32_t accumulate(uint32_t arg, const uint32_t val) -{ - arg += (val & 0xffffU); - return (arg & 0xffffU) + (arg >> 16); -} - -/// The flash configuration data is burned into a special OTP block on the target. -/// This data is hashed with a Fletcher checksum, which has the nice property that -/// it can tell us if the endianness is backwards or if we're not talking to the -/// correct device. The checksum value is stored in the last word of the OTP area. -static bool fletcher_checksum(const uint32_t *const otp_data, const size_t otp_data_count, const uint32_t comparison) -{ - uint32_t check_low = 0xffffU; - uint32_t check_high = 0xffffU; - - for (size_t i = 0; i < otp_data_count; i++) { - uint32_t word = otp_data[i]; - // Accumulate low word - check_low = accumulate(check_low, word); - check_high = accumulate(check_high, check_low); - // Accumulate high word - check_low = accumulate(check_low, word >> 16); - check_high = accumulate(check_high, check_low); - } - - uint32_t result = (check_high << 16) | check_low; - DEBUG_TARGET("Comparing result %08" PRIx32 " to check value %08" PRIx32 "\n", result, comparison); - return comparison == result; -} - -static bool tms570_flash_initialize(target_s *const target) -{ - if (target->tms570_flash_initialized) - return true; - DEBUG_TARGET("Initializing flash...\n"); - - // Read the OTP data out of flash. This is protected with a Fletcher checksum - uint32_t otp_data[12]; - for (int i = 0; i < 12; i++) { - const uint32_t value = target_mem32_read32(target, TMS570_FLASH_OTP_BASE + (i * 4)); - otp_data[i] = read_be4((const uint8_t *)&value, 0); - DEBUG_TARGET("Flash OTP[0x%08" PRIx32 "]: 0x%08" PRIx32 "\n", TMS570_FLASH_OTP_BASE + (i * 4), otp_data[i]); - } - if (!fletcher_checksum(otp_data, 11, otp_data[11])) { - return false; - } - - // Enable all three banks - const uint32_t fmac = target_mem32_read32(target, TMS570_L2FMC_FMAC_ADDR); - target_mem32_write32(target, TMS570_L2FMC_FMAC_ADDR, fmac | 7); - - // Disable read margin control. - // (Note: previously this set RMBSEL first and then RM0/1, but do both in one write now) - target_mem32_write32(target, TMS570_L2FMC_FSPRD_ADDR, 0); - - // Disable the FSM - target_mem32_write32(target, TMS570_L2FMC_FSM_WR_ENA_ADDR, 0); - - // Copy some timing values from OTP - const uint32_t unk_210 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x210); - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x210, (unk_210 & 0xffff0000) | (otp_data[0] >> 16)); - const uint32_t unk_218 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x218); - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x218, (unk_218 & 0xffff0000) | (otp_data[0] & 0xffff)); - - // Set the 2nd nibble after the first write is completed - const uint32_t unk_21c = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x21c); - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x21c, (unk_21c & 0xffff00f0) | (otp_data[1] & 0xff0f)); - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x21c, (unk_21c & 0xffff0000) | (otp_data[1] & 0xffff)); - - // ??? - const uint32_t unk_214 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x214); - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x214, (unk_214 & 0xffff0fff) | (otp_data[3] & 0xf000)); - - // ??? - const uint32_t unk_220 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x220); - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x220, (unk_220 & 0xffffff00) | ((otp_data[1] >> 24) & 0xff)); - - // ??? - const uint32_t unk_224 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x224); - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x224, (unk_224 & 0xffffff00) | ((otp_data[2] >> 16) & 0xff)); - - // ??? - const uint32_t unk_268 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x268); - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x268, (unk_268 & 0xfffff000) | (otp_data[5] & 0xfff)); - - // ??? - const uint32_t unk_26c = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x26c); - target_mem32_write16( - target, TMS570_L2FMC_BASE_ADDR + 0x26c, (unk_26c & 0xfe00ffff) | ((otp_data[8] & 0x1ff) << 16)); - - // NOTE: This used to be a 16-bit access -- ensure that it's properly swapped - const uint32_t unk_270 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x270); - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x270, unk_270 & 0xfe00ffff); - - const uint32_t unk_278 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x278); - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x278, (unk_278 & 0xffffff80) | ((otp_data[4] - 1) & 0x7f)); - - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x27c, 0x4500); - - // Unlock L2FMC - target_mem32_write32(target, TMS570_L2FMC_FLOCK_ADDR, 0x55aa); - - const uint32_t fvreadct = target_mem32_read32(target, TMS570_L2FMC_FVREADCT_ADDR); - target_mem32_write32(target, TMS570_L2FMC_FVREADCT_ADDR, (fvreadct & 0xfffffff0) | ((otp_data[10] >> 8) & 0xf)); - - target_mem32_write32(target, TMS570_L2FMC_FVNVCT_ADDR, 0); - - target_mem32_write32(target, TMS570_L2FMC_FBSTROBES_ADDR, 0x00010104); - target_mem32_write32(target, TMS570_L2FMC_FPSTROBES_ADDR, 0x103); - target_mem32_write32(target, TMS570_L2FMC_FBMODE_ADDR, 0); - - const uint32_t ftcr = target_mem32_read32(target, TMS570_L2FMC_FTCR_ADDR); - target_mem32_write32(target, TMS570_L2FMC_FTCR_ADDR, ftcr & 0xffffff80); - - const uint32_t fvppct = target_mem32_read32(target, TMS570_L2FMC_FVPPCT_ADDR); - target_mem32_write32(target, TMS570_L2FMC_FVPPCT_ADDR, - (fvppct & 0xffffe0e0) | (((otp_data[9] >> 8) & 0x1f) << 8) | (otp_data[9] & 0x1f)); - - const uint32_t fvwlct = target_mem32_read32(target, TMS570_L2FMC_FVWLCT_ADDR); - target_mem32_write32(target, TMS570_L2FMC_FVWLCT_ADDR, (fvwlct & ~0xf000) | ((otp_data[10] >> 24) & 0xf) << 12); - - const uint32_t fefuse = target_mem32_read32(target, TMS570_L2FMC_FEFUSE_ADDR); - target_mem32_write32(target, TMS570_L2FMC_FEFUSE_ADDR, (fefuse & 0xffffffe0) | ((otp_data[10] >> 16) & 0x1f)); - - const uint32_t unk_a8 = target_mem32_read32(target, TMS570_L2FMC_BASE_ADDR + 0x0a8); - target_mem32_write32(target, TMS570_L2FMC_BASE_ADDR + 0x0a8, (unk_a8 & 0xffffff00) | ((otp_data[3] >> 16) & 0xff)); - - target_mem32_write32(target, TMS570_L2FMC_FPSTROBES_ADDR, 0x103); - - target_mem32_write32(target, TMS570_L2FMC_FBSTROBES_ADDR, 0x10104); - - // Reads as 0x55aa - target_mem32_write32(target, TMS570_L2FMC_FLOCK_ADDR, 0); - - // Re-enable the FSM - const uint32_t fsm = target_mem32_read32(target, TMS570_L2FMC_FSM_WR_ENA_ADDR); - target_mem32_write32(target, TMS570_L2FMC_FSM_WR_ENA_ADDR, (fsm & 0xfffffff8) | 2); - - target->tms570_flash_initialized = true; - return true; -} - -static bool tms570_flash_prepare(target_flash_s *flash) -{ - target_s *const target = flash->t; - - if (!tms570_flash_initialize(target)) { - DEBUG_ERROR("Unable to initialize flash!"); - return false; - } -}