From 27e955667cc94988f9336381984b3d41ff285862 Mon Sep 17 00:00:00 2001 From: Ryan <> Date: Tue, 30 Sep 2025 15:54:31 -0500 Subject: [PATCH] Add arguments to jtag debug utility --- projects/nexys2_host_controller/host/jtag.c | 163 +++++++++++++++----- 1 file changed, 125 insertions(+), 38 deletions(-) diff --git a/projects/nexys2_host_controller/host/jtag.c b/projects/nexys2_host_controller/host/jtag.c index c9ebad0..175cd94 100644 --- a/projects/nexys2_host_controller/host/jtag.c +++ b/projects/nexys2_host_controller/host/jtag.c @@ -1,7 +1,9 @@ #include #include #include +#include #include +#include // Digilent SDK #include @@ -162,7 +164,7 @@ EC_CLEANUP_END } -bool scan(HIF hif) +bool jtag_scan(HIF hif) { assert(hif != hifInvalid); @@ -479,14 +481,64 @@ EC_CLEANUP_END // ----------------------------------------------------------------------------- -int main(int argc, char **argv) +void usage(void) { - (void)argc; - (void)argv; + fprintf(stderr, + "JTAG debugger for CPU0 on Digilent Nexys2\n" + "\n" + "Usage: jtag [options]\n" + "\nConnection options:\n" + " -p, --part Specify device (default: \"Nexys2\")\n" + " -P, --port JTAG port number (default: 0)\n" + "\nOperation options:\n" + " -S, --scan Perform a scan of the JTAG chain\n" + " -s, --step Step the CPU\n" + " -h, --halt Leave the CPU in a halted state\n" + " (default if --step provided)\n" + " -r, --run Leave the CPU in a running state\n" + " -d, --dump Dump CPU state\n" + "\nOutput options:\n" + " -v, --verbose Verbose output; -v -v for more\n" + " -q, --quell Quell progress output; -q -q for less\n" + " -?, --help Display this message\n" + "\n" + ); +} - // Requested settings - char *device = "Nexys2"; - int32_t port = 0; + +int main(int argc, char **argv) +{ + // Parsed options with defaults + int verbose = 0; + int quell = 0; + char *part = "Nexys2"; + int port = 0; + bool scan = false; + bool halt = false; + bool run = false; + int steps = 0; + bool dump = false; + + // Options + int opt; + int option_idx = 0; + struct option longopts[] = { + // Output options + {"help", no_argument, NULL, '?'}, + {"quell", no_argument, NULL, 'q'}, + {"verbose", no_argument, NULL, 'v'}, + + // Connection options + {"part", required_argument, NULL, 'p'}, + {"port", required_argument, NULL, 'P'}, + + // Operation options + {"scan", no_argument, NULL, 'S'}, + {"step", required_argument, NULL, 's'}, + {"halt", no_argument, NULL, 'h'}, + {"run", no_argument, NULL, 'r'}, + {"dump", no_argument, NULL, 'd'}, + }; // Port handle and properties HIF hif = hifInvalid; @@ -496,34 +548,64 @@ int main(int argc, char **argv) // ------------------------------------------------------------- + while ((opt = getopt_long(argc, argv, "?qvSp:P:Ss:hrd", longopts, &option_idx)) != -1) + { + switch (opt) + { + case '?': usage(); exit(0); break; + case 'q': quell++; break; + case 'v': verbose++; break; + + case 'p': part = optarg; break; + case 'P': port = strtol(optarg, NULL, 0); break; + + case 'S': scan = true; break; + case 's': steps += strtol(optarg, NULL, 0); break; + case 'h': halt = true; break; + case 'r': run = true; break; + case 'd': dump = true; break; + + default: + fprintf(stderr, "Invalid option -%c\n\n", opt); + usage(); + exit(1); + break; + } + } + + // ------------------------------------------------------------- + EC_FALSE(DjtgGetVersion(version)); - printf("DJTG version: %s\n", version); + if (verbose) printf("DJTG version: %s\n", version); - EC_FALSE(DmgrOpen(&hif, device)); - printf("Opened device \"%s\"\n", device); + EC_FALSE(DmgrOpen(&hif, part)); + if (verbose) printf("Opened device \"%s\"\n", part); EC_FALSE(DjtgGetPortCount(hif, &port_count)); - printf("Port count: %" PRIi32 "\n", port_count); - for (int32_t i = 0; i < port_count; i++) + if (verbose) { - uint32_t port_properties = 0; - EC_FALSE(DjtgGetPortProperties(hif, i, &port_properties)); - printf("Port %" PRIi32 " properties: 0x%08" PRIx32 "\n", i, port_properties); - printf(" %c JtgSetSpeed\n", port_properties & dprpJtgSetSpeed ? 'y' : 'n'); - printf(" %c JtgSetPinState\n", port_properties & dprpJtgSetPinState ? 'y' : 'n'); - printf(" %c JtgWait\n", port_properties & dprpJtgWait ? 'y' : 'n'); - printf(" %c JtgBatch\n", port_properties & dprpJtgBatch ? 'y' : 'n'); - printf(" %c JtgSetAuxReset\n", port_properties & dprpJtgSetAuxReset ? 'y' : 'n'); - printf(" %c JtgSetGetGpio\n", port_properties & dprpJtgSetGetGpio ? 'y' : 'n'); - - if (port_properties & dprpJtgBatch) + printf("Port count: %" PRIi32 "\n", port_count); + for (int32_t i = 0; i < port_count; i++) { - uint32_t batch_properties = 0; - EC_FALSE(DjtgGetBatchProperties(hif, i, &batch_properties)); - printf(" Batch properties:\n"); - printf(" %c WaitUs\n", batch_properties & djbpWaitUs ? 'y' : 'n'); - printf(" %c SetAuxReset\n", batch_properties & djbpSetAuxReset ? 'y' : 'n'); - printf(" %c SetGetGpio\n", batch_properties & djbpSetGetGpio ? 'y' : 'n'); + uint32_t port_properties = 0; + EC_FALSE(DjtgGetPortProperties(hif, i, &port_properties)); + printf("Port %" PRIi32 " properties: 0x%08" PRIx32 "\n", i, port_properties); + printf(" %c JtgSetSpeed\n", port_properties & dprpJtgSetSpeed ? 'y' : 'n'); + printf(" %c JtgSetPinState\n", port_properties & dprpJtgSetPinState ? 'y' : 'n'); + printf(" %c JtgWait\n", port_properties & dprpJtgWait ? 'y' : 'n'); + printf(" %c JtgBatch\n", port_properties & dprpJtgBatch ? 'y' : 'n'); + printf(" %c JtgSetAuxReset\n", port_properties & dprpJtgSetAuxReset ? 'y' : 'n'); + printf(" %c JtgSetGetGpio\n", port_properties & dprpJtgSetGetGpio ? 'y' : 'n'); + + if (port_properties & dprpJtgBatch) + { + uint32_t batch_properties = 0; + EC_FALSE(DjtgGetBatchProperties(hif, i, &batch_properties)); + printf(" Batch properties:\n"); + printf(" %c WaitUs\n", batch_properties & djbpWaitUs ? 'y' : 'n'); + printf(" %c SetAuxReset\n", batch_properties & djbpSetAuxReset ? 'y' : 'n'); + printf(" %c SetGetGpio\n", batch_properties & djbpSetGetGpio ? 'y' : 'n'); + } } } @@ -534,25 +616,30 @@ int main(int argc, char **argv) } EC_FALSE(DjtgEnableEx(hif, port)); - printf("Opened JTAG port %" PRIi32 "\n", port); + if (verbose) printf("Opened JTAG port %" PRIi32 "\n", port); EC_FALSE(DjtgGetSpeed(hif, &speed)); - printf("Port speed: %" PRIi32 " Hz\n", speed); + if (verbose) printf("Port speed: %" PRIi32 " Hz\n", speed); // ------------------------------------------------------------- // Perform a scan to see what's on the chain - //EC_FALSE(scan(hif)); - printf("\n\n"); + if (scan) EC_FALSE(jtag_scan(hif)); - EC_FALSE(cpu_halt(hif)); - EC_FALSE(cpu_state(hif)); - for (size_t i = 0; i < 20; i++) + if (steps > 0) { - EC_FALSE(cpu_step(hif)); - EC_FALSE(cpu_state(hif)); + EC_FALSE(cpu_halt(hif)); + for (size_t i = 0; i < 20; i++) + { + EC_FALSE(cpu_step(hif)); + EC_FALSE(cpu_state(hif)); + } } + if (halt) EC_FALSE(cpu_halt(hif)); + if (dump) EC_FALSE(cpu_state(hif)); + if (run) EC_FALSE(cpu_run(hif)); + // ------------------------------------------------------------- // Close JTAG session -- 2.43.0