Skip to content

Commit

Permalink
experimental: start working towards a native implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
perigoso authored and rg-silva committed Nov 25, 2024
1 parent 1ce1332 commit 2a30df5
Show file tree
Hide file tree
Showing 10 changed files with 584 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ bool cmd_rvswd_scan(target_s *target, int argc, const char **argv)
#if CONFIG_BMDA == 1
scan_result = bmda_rvswd_scan();
#else
scan_result = false;
scan_result = rvswd_scan();
#endif
}
CATCH () {
Expand Down Expand Up @@ -400,7 +400,7 @@ bool cmd_auto_scan(target_s *target, int argc, const char **argv)
#if CONFIG_BMDA == 1
scan_result = bmda_rvswd_scan();
#else
scan_result = false;
scan_result = rvswd_scan();
#endif
if (!scan_result)
gdb_out("RVSWD scan found no devices.\n");
Expand Down
44 changes: 44 additions & 0 deletions src/include/rvswd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef INCLUDE_RVSWD_H
#define INCLUDE_RVSWD_H

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

/* Functions interface talking RVSWD */
typedef struct rvswd_proc {
/* Perform a clock_cycles read */
uint32_t (*seq_in)(size_t clock_cycles);
/* Perform a clock_cycles read + parity */
bool (*seq_in_parity)(uint32_t *ret, size_t clock_cycles);
/* Perform a clock_cycles write with the provided data */
void (*seq_out)(uint32_t tms_states, size_t clock_cycles);
/* Perform a clock_cycles write + parity with the provided data */
void (*seq_out_parity)(uint32_t tms_states, size_t clock_cycles);
} rvswd_proc_s;

extern rvswd_proc_s rvswd_proc;

void rvswd_init(void);

#endif /* INCLUDE_RVSWD_H */
3 changes: 3 additions & 0 deletions src/include/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ bool bmda_rvswd_scan(void);
#endif
bool adiv5_swd_scan(uint32_t targetid);
bool jtag_scan(void);
#ifdef PLATFORM_HAS_RVSWD
bool rvswd_scan(void);
#endif

size_t target_foreach(void (*callback)(size_t index, target_s *target, void *context), void *context);
void target_list_free(void);
Expand Down
1 change: 1 addition & 0 deletions src/platforms/common/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ platform_common_sources = files(
'aux_serial.c',
'jtagtap.c',
'swdptap.c',
'rvswd.c',
'usb.c',
'usb_dfu_stub.c',
'usb_serial.c',
Expand Down
197 changes: 197 additions & 0 deletions src/platforms/common/rvswd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/* This file implements the SW-DP interface. */

#include "general.h"
#include "platform.h"
#include "timing.h"
#include "rvswd.h"
#include "maths_utils.h"

// FIXME: reusing the SWD macros for now
#if !defined(SWDIO_IN_PORT)
#define SWDIO_IN_PORT SWDIO_PORT
#endif
#if !defined(SWDIO_IN_PIN)
#define SWDIO_IN_PIN SWDIO_PIN
#endif

// typedef enum swdio_status_e {
// SWDIO_STATUS_FLOAT = 0,
// SWDIO_STATUS_DRIVE
// } swdio_status_t;

rvswd_proc_s rvswd_proc;

// static void swdptap_turnaround(swdio_status_t dir) __attribute__((optimize(3)));
// static uint32_t swdptap_seq_in(size_t clock_cycles) __attribute__((optimize(3)));
// static bool swdptap_seq_in_parity(uint32_t *ret, size_t clock_cycles) __attribute__((optimize(3)));
// static void swdptap_seq_out(uint32_t tms_states, size_t clock_cycles) __attribute__((optimize(3)));
// static void swdptap_seq_out_parity(uint32_t tms_states, size_t clock_cycles) __attribute__((optimize(3)));

void rvswd_init(void)
{
// rvswd_proc.seq_in = swdptap_seq_in;
// rvswd_proc.seq_in_parity = swdptap_seq_in_parity;
// rvswd_proc.seq_out = swdptap_seq_out;
// rvswd_proc.seq_out_parity = swdptap_seq_out_parity;
}

// static void swdptap_turnaround(const swdio_status_t dir)
// {
// static swdio_status_t olddir = SWDIO_STATUS_FLOAT;
// /* Don't turnaround if direction not changing */
// if (dir == olddir)
// return;
// olddir = dir;

// #ifdef DEBUG_SWD_BITS
// DEBUG_INFO("%s", dir ? "\n-> " : "\n<- ");
// #endif

// if (dir == SWDIO_STATUS_FLOAT) {
// SWDIO_MODE_FLOAT();
// } else
// gpio_clear(SWCLK_PORT, SWCLK_PIN);

// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter)
// continue;

// gpio_set(SWCLK_PORT, SWCLK_PIN);
// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter)
// continue;

// if (dir == SWDIO_STATUS_DRIVE) {
// gpio_clear(SWCLK_PORT, SWCLK_PIN);
// SWDIO_MODE_DRIVE();
// }
// }

// static uint32_t swdptap_seq_in_clk_delay(size_t clock_cycles) __attribute__((optimize(3)));

// 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) {
// gpio_clear(SWCLK_PORT, SWCLK_PIN);
// value |= gpio_get(SWDIO_IN_PORT, SWDIO_IN_PIN) ? 1U << cycle : 0U;
// 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;
// }
// gpio_clear(SWCLK_PORT, SWCLK_PIN);
// 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)
// {
// uint32_t value = 0;
// for (size_t cycle = 0; cycle < clock_cycles; ++cycle) {
// gpio_clear(SWCLK_PORT, SWCLK_PIN);
// value |= gpio_get(SWDIO_IN_PORT, SWDIO_IN_PIN) ? 1U << cycle : 0U;
// gpio_set(SWCLK_PORT, SWCLK_PIN);
// __asm__("nop");
// }
// gpio_clear(SWCLK_PORT, SWCLK_PIN);
// return value;
// }

// static uint32_t swdptap_seq_in(size_t clock_cycles)
// {
// swdptap_turnaround(SWDIO_STATUS_FLOAT);
// if (target_clk_divider != UINT32_MAX)
// return swdptap_seq_in_clk_delay(clock_cycles);
// else // NOLINT(readability-else-after-return)
// return swdptap_seq_in_no_delay(clock_cycles);
// }

// static bool swdptap_seq_in_parity(uint32_t *ret, size_t clock_cycles)
// {
// const uint32_t result = swdptap_seq_in(clock_cycles);
// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter)
// continue;

// const bool parity = calculate_odd_parity(result);
// const bool bit = gpio_get(SWDIO_IN_PORT, SWDIO_IN_PIN);

// gpio_set(SWCLK_PORT, SWCLK_PIN);
// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter)
// continue;

// *ret = result;
// /* Terminate the read cycle now */
// swdptap_turnaround(SWDIO_STATUS_DRIVE);
// return parity != bit;
// }

// static void swdptap_seq_out_clk_delay(uint32_t tms_states, size_t clock_cycles) __attribute__((optimize(3)));

// 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_clear(SWCLK_PORT, SWCLK_PIN);
// gpio_set_val(SWDIO_PORT, SWDIO_PIN, tms_states & (1 << cycle));
// 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;
// }
// gpio_clear(SWCLK_PORT, SWCLK_PIN);
// }

// static void swdptap_seq_out_no_delay(uint32_t tms_states, size_t clock_cycles) __attribute__((optimize(3)));

// 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_clear(SWCLK_PORT, SWCLK_PIN);
// gpio_set_val(SWDIO_PORT, SWDIO_PIN, tms_states & (1 << cycle));
// gpio_set(SWCLK_PORT, SWCLK_PIN);
// }
// gpio_clear(SWCLK_PORT, SWCLK_PIN);
// }

// static void swdptap_seq_out(const uint32_t tms_states, const size_t clock_cycles)
// {
// swdptap_turnaround(SWDIO_STATUS_DRIVE);
// if (target_clk_divider != UINT32_MAX)
// swdptap_seq_out_clk_delay(tms_states, clock_cycles);
// else
// swdptap_seq_out_no_delay(tms_states, clock_cycles);
// }

// static void swdptap_seq_out_parity(const uint32_t tms_states, const size_t clock_cycles)
// {
// const bool parity = calculate_odd_parity(tms_states);
// swdptap_seq_out(tms_states, clock_cycles);
// gpio_set_val(SWDIO_PORT, SWDIO_PIN, parity);
// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter)
// continue;
// gpio_set(SWCLK_PORT, SWCLK_PIN);
// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter)
// continue;
// gpio_clear(SWCLK_PORT, SWCLK_PIN);
// }
2 changes: 2 additions & 0 deletions src/platforms/hosted/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "platform.h"
#include "jtagtap.h"
#include "swd.h"
#include "rvswd.h"
#include "target.h"
#include "target_internal.h"
#include "adiv5.h"
Expand Down Expand Up @@ -64,6 +65,7 @@ bmda_probe_s bmda_probe_info;
#ifndef ENABLE_GPIOD
jtag_proc_s jtag_proc;
swd_proc_s swd_proc;
rvswd_proc_s rvswd_proc;
#endif

static uint32_t max_frequency = 4000000U;
Expand Down
1 change: 1 addition & 0 deletions src/platforms/native/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#define PLATFORM_HAS_TRACESWO
#define PLATFORM_HAS_POWER_SWITCH
#define PLATFORM_HAS_RVSWD

#if ENABLE_DEBUG == 1
#define PLATFORM_HAS_DEBUG
Expand Down
1 change: 1 addition & 0 deletions src/target/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ target_common_sources = files(
'gdb_reg.c',
'jtag_devs.c',
'jtag_scan.c',
'rvswd_scan.c',
'semihosting.c',
'sfdp.c',
'spi.c',
Expand Down
Loading

0 comments on commit 2a30df5

Please sign in to comment.