Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0ace4b9
icepick: Begun building support for the TI ICEPick controller
dragonmux Jan 22, 2024
c11eecf
icepick: Implemented a custom routine for writing the IR of the ICEPi…
dragonmux Jan 23, 2024
92ec07b
icepick: Implemented a custom routine for shifting the DR of the ICEP…
dragonmux Jan 23, 2024
1af653c
icepick: Implemented reading out the ICEPick configuration registers
dragonmux Jan 22, 2024
f154ed2
icepick: Implemented writing ICEPick configuration registers
dragonmux Jan 23, 2024
1a2a67c
icepick: Implemented logic for scanning through and activating all av…
dragonmux Jan 23, 2024
a58d32d
icepick: Implemented configuration logic for the cores attached via t…
dragonmux Jan 23, 2024
88786ea
icepick: Handle the re-scan portion of the ICEPick operations
dragonmux Jan 23, 2024
c4b6549
am335x: Implemented identification of the Cortex-M3 part of the proce…
dragonmux Jan 26, 2024
d5b1563
dap_jtag: add dap_jtag_cycle for CMSIS-DAP devices
xobs Jan 30, 2025
67470d1
rename target_mem_read32 -> target_mem32_read32
xobs Jan 30, 2025
a5113e5
icepick: support type c icepick devies
xobs Jan 30, 2025
d2197dd
adi: add entries for Cortex-R5
xobs Jan 30, 2025
02dee21
tms570: add basic support for TI TMS570
xobs Jan 30, 2025
ee3ebab
cortexar: hack to get tms570 working
xobs Apr 1, 2025
4f8ebed
work to remove swap32()
xobs Apr 1, 2025
7845af3
cortexar: fully remove swap32 and memcpy
xobs Apr 2, 2025
9e65c1e
tms570: swap check word since this target is BE
xobs Apr 2, 2025
ad6a8ff
incorporate feedback on patch-in-progress
xobs Apr 3, 2025
6888a48
tms570: remove fprintf call
xobs Apr 15, 2025
828ecc8
fixup clang-formatting
xobs Apr 15, 2025
514b5e0
manually fix formatting errors
xobs Apr 15, 2025
94ca0c7
tms570 wip: get init working
xobs Apr 25, 2025
cf0960e
hosted: assert ntrst as part of connecting
xobs Jun 3, 2025
fb65ae5
jtag_scan: split out `jtag_discover()`
xobs Jun 3, 2025
fd8080c
rtt: get working with big endian
xobs Jun 3, 2025
9351065
remove tms570 flash blocks since they do not work
xobs Oct 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 32 additions & 0 deletions src/include/buffer_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -89,6 +113,14 @@ 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)
Expand Down
3 changes: 3 additions & 0 deletions src/include/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -71,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 */
Expand Down
28 changes: 28 additions & 0 deletions src/platforms/hosted/dap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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};
Expand Down
2 changes: 2 additions & 0 deletions src/platforms/hosted/dap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions src/platforms/hosted/dap_jtag.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -52,12 +53,15 @@ 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;
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)
Expand Down Expand Up @@ -145,3 +149,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);
}
50 changes: 37 additions & 13 deletions src/rtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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++)
Expand All @@ -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]);
}
}

Expand Down Expand Up @@ -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) {
Expand All @@ -287,16 +296,18 @@ 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;
}

/* 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;
}

Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions src/target/adi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)")},
Expand Down
63 changes: 63 additions & 0 deletions src/target/am335x.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2024 1BitSquared <info@1bitsquared.com>
* Written by Rachel Mant <git@dragonmux.network>
* 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_mem32_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;
}
Loading
Loading