]> git.the-white-hart.net Git - vhdl/commitdiff
Add arguments to jtag debug utility
authorRyan <>
Tue, 30 Sep 2025 20:54:31 +0000 (15:54 -0500)
committerRyan <>
Tue, 30 Sep 2025 20:54:31 +0000 (15:54 -0500)
projects/nexys2_host_controller/host/jtag.c

index c9ebad0f171ee4c9ada962176f1170f1826787c1..175cd94f6ee8010e5ce0199936186baf1a00a164 100644 (file)
@@ -1,7 +1,9 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <inttypes.h>
+#include <stdlib.h>
 #include <stdio.h>
+#include <getopt.h>
 
 // Digilent SDK
 #include <dpcdecl.h>
@@ -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 <name>      Specify device (default: \"Nexys2\")\n"
+               "  -P, --port <portnum>   JTAG port number (default: 0)\n"
+               "\nOperation options:\n"
+               "  -S, --scan             Perform a scan of the JTAG chain\n"
+               "  -s, --step <steps>     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