Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions src/include/jtagtap.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ typedef struct jtag_proc_s {
extern jtag_proc_t jtag_proc;

/* generic soft reset: 1, 1, 1, 1, 1, 0 */
#define jtagtap_soft_reset() jtag_proc.jtagtap_tms_seq(0x1F, 6)
#define jtagtap_soft_reset() jtag_proc.jtagtap_tms_seq(0x1fU, 6)

/* Goto Shift-IR: 1, 1, 0, 0 */
#define jtagtap_shift_ir() jtag_proc.jtagtap_tms_seq(0x03, 4)
#define jtagtap_shift_ir() jtag_proc.jtagtap_tms_seq(0x03U, 4)

/* Goto Shift-DR: 1, 0, 0 */
#define jtagtap_shift_dr() jtag_proc.jtagtap_tms_seq(0x01, 3)
#define jtagtap_shift_dr() jtag_proc.jtagtap_tms_seq(0x01U, 3)

/* Goto Run-test/Idle: 1, 1, 0 */
#define jtagtap_return_idle(cycles) jtag_proc.jtagtap_tms_seq(0x01, (cycles) + 1U)
Expand Down
112 changes: 51 additions & 61 deletions src/platforms/common/jtagtap.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,11 @@ int jtagtap_init()
jtag_proc.jtagtap_cycle = jtagtap_cycle;
jtag_proc.tap_idle_cycles = 1;

/* Go to JTAG mode for SWJ-DP */
/* Ensure we're in JTAG mode */
for (size_t i = 0; i <= 50U; ++i)
jtagtap_next(1, 0); /* Reset SW-DP */
jtagtap_next(true, false); /* 50 idle cylces for SWD reset */
jtagtap_tms_seq(0xe73cU, 16U); /* SWD to JTAG sequence */
jtagtap_soft_reset();

return 0;
}

Expand Down Expand Up @@ -100,31 +99,30 @@ static bool jtagtap_next(const bool tms, const bool tdi)
return jtagtap_next_no_delay();
}

static void jtagtap_tms_seq_swd_delay(uint32_t tms_states, size_t ticks)
static void jtagtap_tms_seq_swd_delay(uint32_t tms_states, const size_t clock_cycles)
{
while (ticks) {
const bool state = tms_states & 1;
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
const bool state = tms_states & 1U;
gpio_set_val(TMS_PORT, TMS_PIN, state);
gpio_set(TCK_PORT, TCK_PIN);
for (volatile int32_t cnt = swd_delay_cnt - 2; cnt > 0; cnt--)
continue;
tms_states >>= 1;
ticks--;
tms_states >>= 1U;
gpio_clear(TCK_PORT, TCK_PIN);
for (volatile int32_t cnt = swd_delay_cnt - 2; cnt > 0; cnt--)
continue;
}
}

static void jtagtap_tms_seq_no_delay(uint32_t tms_states, size_t ticks)
static void jtagtap_tms_seq_no_delay(uint32_t tms_states, const size_t clock_cycles)
{
while (ticks) {
const bool state = tms_states & 1;
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
const bool state = tms_states & 1U;
gpio_set_val(TMS_PORT, TMS_PIN, state);
gpio_set(TCK_PORT, TCK_PIN);
tms_states >>= 1;
tms_states >>= 1U;
__asm__("nop");
__asm__("nop");
ticks--;
gpio_clear(TCK_PORT, TCK_PIN);
}
}
Expand All @@ -139,92 +137,89 @@ static void jtagtap_tms_seq(const uint32_t tms_states, const size_t ticks)
}

static void jtagtap_tdi_tdo_seq_swd_delay(
const uint8_t *const data_in, uint8_t *const data_out, const bool final_tms, size_t clock_cycles)
const uint8_t *const data_in, uint8_t *const data_out, const bool final_tms, const size_t clock_cycles)
{
size_t byte = 0;
size_t index = 0;
uint8_t value = 0;
while (clock_cycles--) {
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
const size_t bit = cycle & 7U;
const size_t byte = cycle >> 3U;
/* On the last cycle, assert final_tms to TMS_PIN */
gpio_set_val(TMS_PORT, TMS_PIN, clock_cycles ? false : final_tms);
gpio_set_val(TMS_PORT, TMS_PIN, cycle + 1 >= clock_cycles && final_tms);
/* Set up the TDI pin and start the clock cycle */
gpio_set_val(TDI_PORT, TDI_PIN, data_in[byte] & (1U << index));
gpio_set_val(TDI_PORT, TDI_PIN, data_in[byte] & (1U << bit));
gpio_set(TCK_PORT, TCK_PIN);
for (volatile int32_t cnt = swd_delay_cnt - 2; cnt > 0; cnt--)
continue;
/* If TDO is high, store a 1 in the appropriate position in the value being accumulated */
if (gpio_get(TDO_PORT, TDO_PIN))
value |= (1 << index);
if (index++ == 7U) {
data_out[byte++] = value;
index = 0;
value |= (1 << bit);
if (bit == 7U) {
data_out[byte] = value;
value = 0;
}
/* Finish the clock cycle */
gpio_clear(TCK_PORT, TCK_PIN);
for (volatile int32_t cnt = swd_delay_cnt - 2; cnt > 0; cnt--)
continue;
}
if (index)
const size_t bit = (clock_cycles - 1U) & 7U;
const size_t byte = (clock_cycles - 1U) >> 3U;
if (bit)
data_out[byte] = value;
}

static void jtagtap_tdi_tdo_seq_no_delay(
const uint8_t *const data_in, uint8_t *const data_out, const bool final_tms, size_t clock_cycles)
const uint8_t *const data_in, uint8_t *const data_out, const bool final_tms, const size_t clock_cycles)
{
size_t byte = 0;
size_t index = 0;
uint8_t value = 0;
while (clock_cycles--) {
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
const size_t bit = cycle & 7U;
const size_t byte = cycle >> 3U;
/* On the last tick, assert final_tms to TMS_PIN */
gpio_set_val(TMS_PORT, TMS_PIN, clock_cycles ? false : final_tms);
gpio_set_val(TMS_PORT, TMS_PIN, cycle + 1 >= clock_cycles && final_tms);
/* Set up the TDI pin and start the clock cycle */
gpio_set_val(TDI_PORT, TDI_PIN, data_in[byte] & (1U << index));
gpio_set_val(TDI_PORT, TDI_PIN, data_in[byte] & (1U << bit));
gpio_set(TCK_PORT, TCK_PIN);
/* If TDO is high, store a 1 in the appropriate position in the value being accumulated */
if (gpio_get(TDO_PORT, TDO_PIN))
value |= (1 << index);
value |= (1 << bit);
/* If we've got to the next whole byte, store the accumulated value and reset state */
if (index++ == 7U) {
data_out[byte++] = value;
index = 0;
if (bit == 7U) {
data_out[byte] = value;
value = 0;
}
/* Finish the clock cycle */
gpio_clear(TCK_PORT, TCK_PIN);
}
if (index)
const size_t bit = (clock_cycles - 1U) & 7U;
const size_t byte = (clock_cycles - 1U) >> 3U;
if (bit)
data_out[byte] = value;
}

static void jtagtap_tdi_tdo_seq(
uint8_t *const data_out, const bool final_tms, const uint8_t *const data_in, size_t ticks)
uint8_t *const data_out, const bool final_tms, const uint8_t *const data_in, size_t clock_cycles)
{
gpio_clear(TMS_PORT, TMS_PIN);
gpio_clear(TDI_PORT, TDI_PIN);
if (swd_delay_cnt)
jtagtap_tdi_tdo_seq_swd_delay(data_in, data_out, final_tms, ticks);
jtagtap_tdi_tdo_seq_swd_delay(data_in, data_out, final_tms, clock_cycles);
else
jtagtap_tdi_tdo_seq_no_delay(data_in, data_out, final_tms, ticks);
jtagtap_tdi_tdo_seq_no_delay(data_in, data_out, final_tms, clock_cycles);
}

static void jtagtap_tdi_seq_swd_delay(const uint8_t *const data_in, const bool final_tms, size_t clock_cycles)
{
size_t byte = 0;
size_t index = 0;
while (clock_cycles--) {
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
const size_t bit = cycle & 7U;
const size_t byte = cycle >> 3U;
/* On the last tick, assert final_tms to TMS_PIN */
gpio_set_val(TMS_PORT, TMS_PIN, clock_cycles ? false : final_tms);
gpio_set_val(TMS_PORT, TMS_PIN, cycle + 1 >= clock_cycles && final_tms);
/* Set up the TDI pin and start the clock cycle */
gpio_set_val(TDI_PORT, TDI_PIN, data_in[byte] & (1U << index));
gpio_set_val(TDI_PORT, TDI_PIN, data_in[byte] & (1U << bit));
gpio_set(TCK_PORT, TCK_PIN);
for (volatile int32_t cnt = swd_delay_cnt - 2; cnt > 0; cnt--)
continue;
/* If we've used a whole byte, reset state for the next */
if (index++ == 7U) {
++byte;
index = 0;
}
/* Finish the clock cycle */
gpio_clear(TCK_PORT, TCK_PIN);
for (volatile int32_t cnt = swd_delay_cnt - 2; cnt > 0; cnt--)
Expand All @@ -234,31 +229,26 @@ static void jtagtap_tdi_seq_swd_delay(const uint8_t *const data_in, const bool f

static void jtagtap_tdi_seq_no_delay(const uint8_t *const data_in, const bool final_tms, size_t clock_cycles)
{
size_t byte = 0;
size_t index = 0;
while (clock_cycles--) {
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
const size_t bit = cycle & 7U;
const size_t byte = cycle >> 3U;
/* On the last tick, assert final_tms to TMS_PIN */
gpio_set_val(TMS_PORT, TMS_PIN, clock_cycles ? false : final_tms);
gpio_set_val(TMS_PORT, TMS_PIN, cycle + 1 >= clock_cycles && final_tms);
/* Set up the TDI pin and start the clock cycle */
gpio_set_val(TDI_PORT, TDI_PIN, data_in[byte] & (1U << index));
gpio_set_val(TDI_PORT, TDI_PIN, data_in[byte] & (1U << bit));
gpio_set(TCK_PORT, TCK_PIN);
/* If we've used a whole byte, reset state for the next */
if (index++ == 7U) {
++byte;
index = 0;
}
/* Finish the clock cycle */
gpio_clear(TCK_PORT, TCK_PIN);
}
}

static void jtagtap_tdi_seq(const bool final_tms, const uint8_t *const data_in, const size_t ticks)
static void jtagtap_tdi_seq(const bool final_tms, const uint8_t *const data_in, const size_t clock_cycles)
{
gpio_clear(TMS_PORT, TMS_PIN);
if (swd_delay_cnt)
jtagtap_tdi_seq_swd_delay(data_in, final_tms, ticks);
jtagtap_tdi_seq_swd_delay(data_in, final_tms, clock_cycles);
else
jtagtap_tdi_seq_no_delay(data_in, final_tms, ticks);
jtagtap_tdi_seq_no_delay(data_in, final_tms, clock_cycles);
}

static void jtagtap_cycle_swd_delay(const size_t clock_cycles)
Expand Down
8 changes: 4 additions & 4 deletions src/target/adiv5_jtagdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ uint32_t fw_adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, uint16_t addr,
uint64_t response;
uint8_t ack;

jtag_dev_write_ir(&jtag_proc, dp->dp_jd_index, APnDP ? IR_APACC : IR_DPACC);
jtag_dev_write_ir(dp->dp_jd_index, APnDP ? IR_APACC : IR_DPACC);

platform_timeout timeout;
platform_timeout_set(&timeout, 250);
do {
jtag_dev_shift_dr(&jtag_proc, dp->dp_jd_index, (uint8_t *)&response, (uint8_t *)&request, 35);
jtag_dev_shift_dr(dp->dp_jd_index, (uint8_t *)&response, (uint8_t *)&request, 35);
ack = response & 0x07;
} while (!platform_timeout_is_expired(&timeout) && ack == JTAGDP_ACK_WAIT);

Expand All @@ -104,6 +104,6 @@ uint32_t fw_adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, uint16_t addr,
void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort)
{
uint64_t request = (uint64_t)abort << 3;
jtag_dev_write_ir(&jtag_proc, dp->dp_jd_index, IR_ABORT);
jtag_dev_shift_dr(&jtag_proc, dp->dp_jd_index, NULL, (const uint8_t *)&request, 35);
jtag_dev_write_ir(dp->dp_jd_index, IR_ABORT);
jtag_dev_shift_dr(dp->dp_jd_index, NULL, (const uint8_t *)&request, 35);
}
20 changes: 10 additions & 10 deletions src/target/jtag_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ uint32_t jtag_scan(const uint8_t *irlens)
return jtag_dev_count;
}

void jtag_dev_write_ir(jtag_proc_t *jp, const uint8_t dev_index, const uint32_t ir)
void jtag_dev_write_ir(const uint8_t dev_index, const uint32_t ir)
{
jtag_dev_t *device = &jtag_devs[dev_index];
if (ir == device->current_ir)
Expand All @@ -242,22 +242,22 @@ void jtag_dev_write_ir(jtag_proc_t *jp, const uint8_t dev_index, const uint32_t
device->current_ir = ir;

jtagtap_shift_ir();
jp->jtagtap_tdi_seq(false, ones, device->ir_prescan);
jp->jtagtap_tdi_seq(!device->ir_postscan, (const uint8_t *)&ir, device->ir_len);
jp->jtagtap_tdi_seq(true, ones, device->ir_postscan);
jtag_proc.jtagtap_tdi_seq(false, ones, device->ir_prescan);
jtag_proc.jtagtap_tdi_seq(!device->ir_postscan, (const uint8_t *)&ir, device->ir_len);
jtag_proc.jtagtap_tdi_seq(true, ones, device->ir_postscan);
jtagtap_return_idle(1);
}

void jtag_dev_shift_dr(
jtag_proc_t *jp, const uint8_t dev_index, uint8_t *data_out, const uint8_t *data_in, const size_t clock_cycles)
void jtag_dev_shift_dr(const uint8_t dev_index, uint8_t *data_out, const uint8_t *data_in, const size_t clock_cycles)
{
jtag_dev_t *device = &jtag_devs[dev_index];
jtagtap_shift_dr();
jp->jtagtap_tdi_seq(false, ones, device->dr_prescan);
jtag_proc.jtagtap_tdi_seq(false, ones, device->dr_prescan);
if (data_out)
jp->jtagtap_tdi_tdo_seq((uint8_t *)data_out, !device->dr_postscan, (const uint8_t *)data_in, clock_cycles);
jtag_proc.jtagtap_tdi_tdo_seq(
(uint8_t *)data_out, !device->dr_postscan, (const uint8_t *)data_in, clock_cycles);
else
jp->jtagtap_tdi_seq(!device->dr_postscan, (const uint8_t *)data_in, clock_cycles);
jp->jtagtap_tdi_seq(true, ones, device->dr_postscan);
jtag_proc.jtagtap_tdi_seq(!device->dr_postscan, (const uint8_t *)data_in, clock_cycles);
jtag_proc.jtagtap_tdi_seq(true, ones, device->dr_postscan);
jtagtap_return_idle(1);
}
4 changes: 2 additions & 2 deletions src/target/jtag_scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ typedef struct jtag_dev_s {
extern struct jtag_dev_s jtag_devs[JTAG_MAX_DEVS + 1U];
extern uint32_t jtag_dev_count;

void jtag_dev_write_ir(jtag_proc_t *jp, uint8_t jd_index, uint32_t ir);
void jtag_dev_shift_dr(jtag_proc_t *jp, uint8_t jd_index, uint8_t *dout, const uint8_t *din, size_t ticks);
void jtag_dev_write_ir(uint8_t jd_index, uint32_t ir);
void jtag_dev_shift_dr(uint8_t jd_index, uint8_t *dout, const uint8_t *din, size_t ticks);
void jtag_add_device(uint32_t dev_index, const jtag_dev_t *jtag_dev);

#endif /* TARGET_JTAG_SCAN_H */
50 changes: 26 additions & 24 deletions src/target/jtagtap_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,39 +24,41 @@
#include "general.h"
#include "jtagtap.h"

void jtagtap_tms_seq(uint32_t MS, int ticks)
void jtagtap_tms_seq(const uint32_t tms_states, const size_t clock_cycles)
{
while (ticks--) {
jtagtap_next(MS & 1, 1);
MS >>= 1;
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
const bool tms = (tms_states >> cycle) & 1U;
jtag_proc.jtagtap_next(tms, true);
}
}

void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
void jtagtap_tdi_tdo_seq(
uint8_t *const data_out, const uint8_t final_tms, const uint8_t *const data_in, const size_t clock_cycles)
{
uint8_t index = 1;
while (ticks--) {
if (jtagtap_next(ticks ? 0 : final_tms, *DI & index)) {
*DO |= index;
} else {
*DO &= ~index;
}
if (!(index <<= 1)) {
index = 1;
DI++;
DO++;
uint8_t value = 0;
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
const size_t bit = cycle & 7U;
const size_t byte = cycle >> 3U;
const bool tms = cycle + 1 >= clock_cycles && final_tms;
const bool tdi = data_in[byte] & (1U << bit);

if (jtag_proc.jtagtap_next(tms, tdi))
value |= 1U << bit;

if (bit == 7U) {
data_out[byte] = value;
value = 0;
}
}
}

void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks)
void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *const data_in, const size_t clock_cycles)
{
uint8_t index = 1;
while (ticks--) {
jtagtap_next(ticks ? 0 : final_tms, *DI & index);
if (!(index <<= 1)) {
index = 1;
DI++;
}
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
const size_t bit = cycle & 7U;
const size_t byte = cycle >> 3U;
const bool tms = cycle + 1 >= clock_cycles && final_tms;
const bool tdi = data_in[byte] & (1U << bit);
jtag_proc.jtagtap_next(tms, tdi);
}
}