Skip to content

Commit

Permalink
common/swdptap: adjust timing
Browse files Browse the repository at this point in the history
Make clock cycle more symmetric, especially for `no_delay` variants.

`swdptap_seq_out_no_delay` seems to need the clock clear to be moved
back to the top of the loop, to ensure minimal delay between the falling
edge and the SWDIO change.

Also use a different loop counter that compiles to a `SUBS` `BCC`/`BCS`
pair, instead of using an explicit `CMP`.
  • Loading branch information
tlyu committed Jul 12, 2024
1 parent 37254ca commit caf82d5
Showing 1 changed file with 53 additions and 11 deletions.
64 changes: 53 additions & 11 deletions src/platforms/common/swdptap.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,29 +99,49 @@ static uint32_t swdptap_seq_in_clk_delay(size_t clock_cycles) __attribute__((opt
static uint32_t swdptap_seq_in_clk_delay(const size_t clock_cycles)
{
uint32_t value = 0;
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
if (!clock_cycles)
return 0;
for (size_t cycle = clock_cycles; cycle--;) {
for (volatile uint32_t counter = target_clk_divider; counter > 0; --counter)
continue;
value |= gpio_get(SWDIO_IN_PORT, SWDIO_IN_PIN) ? 1U << cycle : 0U;
bool bit = gpio_get(SWDIO_IN_PORT, SWDIO_IN_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
for (volatile uint32_t counter = target_clk_divider; counter > 0; --counter)
continue;
value >>= 1U;
value |= (uint32_t)bit << 31U;
/* Reordering barrier */
__asm__("" ::: "memory");
gpio_clear(SWCLK_PORT, SWCLK_PIN);
/* Reordering barrier */
__asm__("" ::: "memory");
}
value >>= (32U - clock_cycles);
return value;
}

static uint32_t swdptap_seq_in_no_delay(size_t clock_cycles) __attribute__((optimize(3)));

static uint32_t swdptap_seq_in_no_delay(const size_t clock_cycles)
{
if (!clock_cycles)
return 0;
uint32_t value = 0;
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
value |= gpio_get(SWDIO_IN_PORT, SWDIO_IN_PIN) ? 1U << cycle : 0U;
for (size_t cycle = clock_cycles; cycle--;) {
/* Reordering barrier */
__asm__("" ::: "memory");
bool bit = gpio_get(SWDIO_IN_PORT, SWDIO_IN_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
__asm__("nop");
__asm__("nop" ::: "memory");
value >>= 1U;
value |= (uint32_t)bit << 31U;
/* Reordering barrier */
__asm__("" ::: "memory");
gpio_clear(SWCLK_PORT, SWCLK_PIN);
/* Reordering barrier */
__asm__("" ::: "memory");
}
value >>= (32U - clock_cycles);
return value;
}

Expand Down Expand Up @@ -159,13 +179,24 @@ static void swdptap_seq_out_clk_delay(uint32_t tms_states, size_t clock_cycles)

static void swdptap_seq_out_clk_delay(const uint32_t tms_states, const size_t clock_cycles)
{
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
gpio_set_val(SWDIO_PORT, SWDIO_PIN, tms_states & (1U << cycle));
uint32_t value = tms_states;
bool bit = value & 1;
if (!clock_cycles)
return;
for (size_t cycle = clock_cycles; cycle--;) {
/* Reordering barrier */
__asm__("" ::: "memory");
gpio_set_val(SWDIO_PORT, SWDIO_PIN, bit);
for (volatile uint32_t counter = target_clk_divider; counter > 0; --counter)
continue;
gpio_set(SWCLK_PORT, SWCLK_PIN);
for (volatile uint32_t counter = target_clk_divider; counter > 0; --counter)
continue;
__asm__("nop" ::: "memory");
value >>= 1U;
bit = value & 1;
/* Reordering barrier */
__asm__("" ::: "memory");
gpio_clear(SWCLK_PORT, SWCLK_PIN);
}
}
Expand All @@ -174,12 +205,23 @@ static void swdptap_seq_out_no_delay(uint32_t tms_states, size_t clock_cycles) _

static void swdptap_seq_out_no_delay(const uint32_t tms_states, const size_t clock_cycles)
{
for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
gpio_set_val(SWDIO_PORT, SWDIO_PIN, tms_states & (1U << cycle));
gpio_set(SWCLK_PORT, SWCLK_PIN);
__asm__("nop");
uint32_t value = tms_states;
bool bit = value & 1;
if (!clock_cycles)
return;
for (size_t cycle = clock_cycles; cycle--;) {
/* Reordering barrier */
__asm__("" ::: "memory");
gpio_clear(SWCLK_PORT, SWCLK_PIN);
gpio_set_val(SWDIO_PORT, SWDIO_PIN, bit);
gpio_set(SWCLK_PORT, SWCLK_PIN);
__asm__("nop" ::: "memory");
value >>= 1U;
bit = value & 1;
/* Reordering barrier */
__asm__("" ::: "memory");
}
gpio_clear(SWCLK_PORT, SWCLK_PIN);
}

static void swdptap_seq_out(const uint32_t tms_states, const size_t clock_cycles)
Expand Down

0 comments on commit caf82d5

Please sign in to comment.