Jump to content
IGNORED

Preview: gdbjag - Source-level 68k and GPU/DSP debugging


Recommended Posts

I'm pushing this a bit earlier than I would normally share one of my projects because it's huge and hence getting kind of hard to maintain in a private branch, and because it's finally in a usable state for those dedicated enough to go through all the necessary steps.

 

Ever read the old threads about how awesome Alpine board debugging was compared to everything else? I do. I got a chance to play with an Alpine board recently, and yeah, the tools are pretty cool compared to the skunkCONSOLEWRITE debugging and hand-rolled instrumentation I usually rely on. However, they require the incredibly rare Alpine hardware, and an ancient PC running an ancient OS or some tricks to get the old 1995 WDB or RDBJAG tools to run, so it's not helping that many people these days. I'll post more about my romp through Alpine land later, but the important part here is that I realized the tools weren't doing anything that magical. @Tursi long ago released jserve, a tool that lets you debug m68k Jaguar code at the source level using GDB, as long as you have a binary with appropriate debug information, meaning an ELF-format binary these days. GDB is extensible, and at its core the jserve tool and its corresponding stub code have all the functionality the Alpine tools relied on, which was basically some interrupt handlers and the ability to do raw reads/writes from/to Jaguar memory. My Jaguar SDK already includes the gpu.db script (By way of Belboz's SDK which mine is derived from, which in turn is derived from the Atari official SDK), which is an Atari DB debugger script implementing a crude precursor to the GPU and DSP debugging features built into the latest versions of WDB and RDBJAG. I wondered, could it be ported to GDB+jserve? The answer, it turns out, is yes, it can. However, like most things, it was a lot more work than I thought it would be when I started.

 

The preview-quality (Let's call it an Alpha) release of this work I pushed to my SDK just now contains the following:

 

  1. Script updates to build the last version of GDB that supported m68k a.out binaries (Version 8.1.1) along with some patches applied to support the f**ked up unique implementation of the COFF executable file format ALN produces. This was a serious pain, as what Atari calls COFF is almost nothing like "real" COFF, and on top of that it turns out ALN, MAC, and the old version of GCC that supports a.out m68k output all generate horrible debug symbols, but it works now, so you can take the same files you'd debug on an Alpine and load them up in GDB to get full line-number, local variable, C function names, etc. debugging on the 68k. All the stuff you'd expect when using GDB in a normal environment, so you can step through C code line-by-line, break on function names, etc.
  2. Script updates to build the python module that wraps my JRISC disassembler library.
  3. Script updates to build a patched version of the jserve Jaguar remote debug stub server. The patches so far just fix the build on Linux and fix reading/writing of GPU memory & registers.
  4. A set of python and GDB command file GDB extensions that introduce JRISC (GPU mostly so far, some DSP support is present) debugging on live Jaguar systems, including the following commands:
    1. gpustuf - Upload support code for the below commands to an unused portion of the reserved memory area below 0x4000 on the Jaguar. Run this before using any of the below commands as soon as you've connected to jserve in GDB. In the future I'll automate the whole process of launching jserve, connecting to it, and running this command, but as I say, the edges are a bit rough right now.
    2. gdisassemble/ddisassemble - Disassemble GPU or DSP code from Jaguar memory. This is used by some of the other commands to disassemble the next GPU instruction to give you some context when you land back in the debugger command line, but you can also use them to disassemble arbitrary regions of memory, or memory at some symbol/line number/etc.
    3. setgpc - Set the current GPU program counter.
    4. stopgpu - Stop the GPU if it is currently running
    5. gogpu - Start the GPU. It will begin executing at the current value of G_PC.
    6. gstepi - Step the GPU <N> instructions in single-step mode, pausing in the debugger again afterwards *without* stopping the GPU, and hence without losing state like pending jumps or the current G_PC value.
    7. gadvance - Run the GPU at full speed until a breakpoint address is reached. The GPU will be stopped afterwards, currently losing state like pending jumps, but the G_PC value will be restored to allowing further single stepping or advancing to another breakpoint.
    8. xg - Dump the values of both banks of GPU registers, decode the G_FLAGS register into a human-readable form, and print G_PC as well. This necessarily clobbers one register (currently hard-coded to be R30) in the current bank, just like in rdbjag/wdb, but if you're clever you can toggle banks or only use this at places where you can otherwise deduce the value of R30 to reduce the impact of that if your code needs all the registers.
    9. xgr - Set the value of a GPU register in either bank. Currently this also clobbers the value of R30 because it must read back all the register values first, but you can set the value of R30 with this command, so see above about dumping/setting registers when R30 is in some known state.
    10. Built-in documentation for all of the above using GDB's help command. E.g., 'help xgr' will tell you how to use xgr. Trust me: The minimal documentation provided here is *much* better than what you get out of rdbjag's equivalent help commands.
    11. The $gpc() and $dpc() convenience functions are introduced, which return the value of G_PC and D_PC respectively when used in GDB expressions. This can be useful when using the other commands. E.g., 'gstepi $gpc() ($gpc() + 16)' will trace from the current GPU instruction to the instruction 16 bytes ahead of it, and 'gdis *$gpc,+32' will disassemble the next GPU instruction and any further instructions in the next 32 bytes.
  5. A GDB wrapper script, gdbjag, that runs the 68k-aout GDB variant with the above extensions loaded.

 

This gives anyone with a Skunkboard (And a Linux PC or VM) GPU debugging functionality very close to that available on an Alpine, except it's actually more stable from what I've seen testing it thus far. So, how do you use it?

 

Well, first you'll need to grab the latest version of my SDK and follow the build instructions in the README.md file here:

 

https://github.com/cubanismo/jaguar-sdk

 

If you've set it up before, note the requirements have grown a bit to accommodate GDB with the TUI interface and python plugin support, and some submodules have been added so you might need a 'git fetch --recurse-submodules && git submodules update --init' to pull them all down.

 

Before we get to debugging, you'll need to build your code using MADMAC and ALN, not rmac/rln, and you'll need to include the flags to generate debug information, which rmac/rln ignore at the moment. My plan is to fix that at well at some point, but for now:

  • Edit ${JAGSDK}/tools/build/jagdefs.mk
  • Uncomment the lines indicated to use mac/aln instead of rmac/rln
  • Change the line that sets CFLAGS to '-O2' to set it to '-O0 -g' instead.
  • Change the line that sets ASMFLAGS to '-fb -g -r$(ASMPAD)' to set it to '-fb -g2 -r$(ASMPAD)'
  • Change the line that sets LINKFLAGS to '-e -g -r...' to '-e -l -g2 -r...' (Don't put a literal ellipsis in. It means leave the rest the same)
  • Save and exit

And then you should be good to go. I recommend going to ${JAGSDK}/jaguar/examples/jaghello and running "make" to build jaghello.cof with full debugging support to follow along with the below examples, but you can use these flags to build other code in the SDK or your own code as well.

 

Now it's time to debug. Connect a Skunkboard to your development system via USB, turn the jaguar on, change to the ${JAGSDK}/tools/src/jserve directory and, as root, run "jserve," E.g.

$ cd "${JAGSDK}/tools/src/jserve"
$ sudo ./jserve

It has to be run from that directory so jserve can find jdb.cof, its Jaguar-side helper code. jserve will spew a bunch of debug info to your terminal, finally indicating it is connected. Your Jaguar screen should be black at this point.

 

Go to another terminal, source the SDK env.sh script there as well, and go to your source/build directory, then load it up in gdbjag. I like to include the "-tui" command line parameter to gdbjag so I get a nice source window above my GDB command prompt that I can follow along in, but I'll leave that out of the examples below to keep the output readable. Using the jaghello.cof example here:

$ cd "${JAGSDK}/jaguar/examples/jaghello"
$ gdbjag jaghello.cof
GNU gdb (GDB) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=aarch64-unknown-linux-gnu --target=m68k-coff".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from jaghello.cof...done.
(gdb)

Hurray! We're finally at a GDB prompt! Now it's time to connect to the Skunkboard debug stub and load our code. Use the command "target remote localhost:4567" to connect, then the "load" command to load the code:

(gdb) target remote localhost:4567
Remote debugging using localhost:4567
?? () at startup.s:41
41			move.l  #$70007,G_END		; big-endian mode
(gdb) load
Loading section .text, size 0x3e0 lma 0x4000
Loading section .data, size 0x410 lma 0x43e0
Start address 0x4000, load size 2032
Transfer rate: 3 KB/sec, 145 bytes/write.
(gdb) 

jserve is really going to be spewing now! Ignore it unless you need to debug jserve itself. It's just logging everything it does to the console at a very high level of verbosity. What's important is we are now ready to run code on the Jaguar. You'll note you can view your assembly listing using GDB's "list" command, and jump to source lines just like with any other instance of GDB running on a program with appropriate debug info available. For now, let's advance to just before jaghello's startup code starts the GPU to set the object list pointer, which happens to be on line 58 in startup.s:

(gdb) advance 58
?? () at startup.s:58
58			move.l  #RISCGO,G_CTRL  	; Go!
(gdb)

At this point, the GPU is all initialized and ready to run some trivial code. Let's step through it line by line for kicks. Note an empty line of input in GDB generally repeats the last command, so we can step through GPU code just by running "gstepi" once and then repeatedly hitting Enter. Before we start using the GPU or DSP debugging features, there's one very important step though: We must run "gpustuf" to load the JRISC helper code onto the Jaguar:

(gdb) gpustuf
Restoring binary file regdumpset-500.bin into memory (0x500 to 0x6be)
(gdb) gstepi
00004086: load    (r0), r1
(gdb) 
00004088: movei   #$f00020, r0
(gdb) 
0000408e: store   r1, (r0)
(gdb) 
00004090: moveq   #0, r0
(gdb) 
00004092: movei   #$f02114, r1
(gdb) 
00004098: store   r0, (r1)
(gdb) 
GPU stopped itself
(gdb)

Cool! Looking at this code, we can deduce that the GPU registers r0 and r1 should now contain the values 0 and 0xf02114 respectively. Let's verify that:

(gdb) xg
G_FLAGS: 009e NZ CS NE  Current Register Bank: 0  G_PC: 000040a0
R00: 00000000 00f02114 00000eec 00000000 03d0dead 00000008 ffffffff 00000000
R08: 00f03668 00000040 00f03110 00f03114 00f034e6 00000015 00f03628 00f03264
R16: e4009814 00000015 00000000 00f03384 00f03378 00f031dc 000000ff ffffffc0
R24: ffffbf67 00f035d0 00f032a8 00000044 00f0336a 00f03314 TRASHED! 096b5050
A00: 00000014 00f03628 00000000 abf377fc 220a0211 00000000 01c614a1 fffebbee
A08: 151c0141 7d6ffeea 00620580 b76b26f7 6d3b1b88 bf6f87bf 2300c351 f97adf27
A16: d0a82591 fa1fedbd 28090000 df6dffd7 02407951 ecf7b3fd 0221864b e5f57aac
A24: 000fffe7 feffdfff b0060088 160fb9dc fffffedf 56fbf7f6 fafadead 00000000
(gdb)

Looks good. Since the GPU is done for the duration of this simple program, let's fiddle with some register values: We'll set r0 in bank 0 (the current bank) to 0xf00df00d and r31 in bank 1 (The inactive bank) to 0xdeadd00d, then verify it worked:

(gdb) xgr 0 0xf00df00d
R0 in bank 0 was: 0x00000000 and is now: 0xf00df00d
(gdb) xgr 31 0xdeadd00d 1
R31 in bank 1 was: 0x00000000 and is now: 0xdeadd00d
(gdb) xg
G_FLAGS: 009e NZ CS NE  Current Register Bank: 0  G_PC: 000040a0
R00: f00df00d 00f02114 00000eec 00000000 03d0dead 00000008 ffffffff 00000000
R08: 00f03668 00000040 00f03110 00f03114 00f034e6 00000015 00f03628 00f03264
R16: e4009814 00000015 00000000 00f03384 00f03378 00f031dc 000000ff ffffffc0
R24: ffffbf67 00f035d0 00f032a8 00000044 00f0336a 00f03314 TRASHED! 096b5050
A00: 00000014 00f03628 00000000 abf377fc 220a0211 00000000 01c614a1 fffebbee
A08: 151c0141 7d6ffeea 00620580 b76b26f7 6d3b1b88 bf6f87bf 2300c351 f97adf27
A16: d0a82591 fa1fedbd 28090000 df6dffd7 02407951 ecf7b3fd 0221864b e5f57aac
A24: 000fffe7 feffdfff b0060088 160fb9dc fffffedf 56fbf7f6 fafadead deadd00d

Cool, that's enough playing with the GPU. Let's continue on to our main program. The C code implementing the actual functionality in jaghello starts in the function "__main." Let's set a breakpoint there and continue until we reach it, taking care to skip over the code that would launch the GPU work we just stepped through above:

(gdb) b __main
Breakpoint 1 at 0x4390: file jag.c, line 51.
(gdb) jump +1
Continuing at 0x4062.

Breakpoint 1, __main () at jag.c:51
51	  jagscreen = (unsigned char *)&vidmem;
(gdb)

OK, now we're in C code. You can run "next" to step through it line-by-line, but to finish up this example, I'd like to instead set a breakpoint on the function DrawChar, and continue on to it. This function is called multiple times to draw each individual character of the string "Hello Jag Users."

(gdb) b DrawChar
Breakpoint 2 at 0x42e6: file jag.c, line 24.
(gdb) c
Continuing.

Breakpoint 2, DrawChar (x=1, y=1, ch=72 'H') at jag.c:24
24	  charloc = ch * F_CHARSIZE;
(gdb)

Note the values of all the local parameter variables are displayed. At this point, you can keep hitting enter to continue past each instance of this breakpoint, and watch the characters of the string appear on-screen one at a time. I'll leave that as an exercise for the reader, since it doesn't translate well to text.

 

Happy debugging!

 

I should note you probably can't expect the GPU debugging to be completely stable at this point. Even running through the relatively simple sequence above only a handful of times while writing this, something went wrong a couple of those times. However, if you're stuck, it's worth checking this out to see if it can get you un-stuck. Just don't trust it too much if it seems to be reporting some impossible register values or something. It could very well be wrong. However, again, it's still more stable than the equivalent Alpine board functionality in my limited testing thus far. Also, since everyone reading the developer forum is a developer (right?), take a look at the JRISC helper code in ${JAGSDK}/tools/src/gpudb, and the plugins/scripts in ${JAGSDK}/jaguar/bin/jag.gdb and ${JAGSDK}/jaguar/bin/gdbjag.py and see if you can spot any errors or suggest any improvements. This is all a work in progress, and I'm going to be looking at rmac+rln debug info support next, so this stuff could use a little outside love in the meantime.

  • Like 13
Link to comment
Share on other sites

Thank you. This is awesome.

 

Sidenote I don't know why Atari referred to the output as COFF. Up until ELF arrived my understanding is output has always been a.out and COFF was some kind of wishful thinking. 

 

 

Edited by JagChris
Link to comment
Share on other sites

ELF became widely used around 1999. I discovered it with a Linux distribution in 1996-1997.

In theory Brainstorm had no particular reason(s) to use the ELF format with their tool chain, during this period, the COFF was the norm.

To my knowledge, gcc 4.4 was the last version to have the COFF maintained, the ELF format became the norm around 2010.

Link to comment
Share on other sites

I should have been clearer. I meant until ELF showed up for the Jag several years ago. 

 

Not showed up in general. 

 

And I meant it looks like Brainstorm was transitioning from a.out to COFF and wandered off midway through. 

Edited by JagChris
Link to comment
Share on other sites

17 hours ago, dilinger said:

In theory Brainstorm had no particular reason(s) to use the ELF format with their tool chain, during this period, the COFF was the norm.

There was a rumor going around that the Atari SDK supported ELF. Fortunately for us this caused Tursi to include ELF support in the Skunkboard.

 

Looking I found no evidence this was ever true and that ELF wasn't even usable until GCC 2.7 or so.

Link to comment
Share on other sites

Note the GDB now built as part of my SDK and its gdbjag wrapper script should auto-detect and work fine with ELF binaries too, so if you're already set up with an ELF toolchain, you can still take advantage of the new GPU/DSP debugging and disassembly features. I'm not trying to spark some COFF Vs. ELF debate. I'm just used to the a.out+COFF toolchain I've been using and went down an interesting rabbit hole figuring out why GDB didn't like the binaries ALN and RLN spit out.

Link to comment
Share on other sites

6 hours ago, 42bs said:

Cool. 

Is it possible to load a rln built COF, just no debug info?

Yes, though GDB will warn that the symbol table is truncated, which I need to investigate. That shouldn't happen solely due to missing debug info. I tested this on a slightly modified version of your gpufire256 demo built using rmac, lyxass and RLN while developing it, for example. Modified because the debug connection locks up for some reason due to the way you init and reset the vsync interrupt. Changing it to the way Atari does it in their startup.s (Only write one word to init, reset one word at a time) gets it working. I'll owe you a beer if you can tell me why ?

Link to comment
Share on other sites

This sounds cool. I miss the days of "debjag", when I could single step through GPU code. So I need to switch for a Linux VM for developing.

4 hours ago, cubanismo said:

Modified because the debug connection locks up for some reason due to the way you init and reset the vsync interrupt. Changing it to the way Atari does it in their startup.s (Only write one word to init, reset one word at a time) gets it working. I'll owe you a beer if you can tell me why ?

You mean this code does block the SKUNK/GDB?

	move.l	#$1f01<<16,d6
	move.l	d6,$E0(a5)

Just to be sure, you did define SKUNK on the command line? W/o no video init is done.

Link to comment
Share on other sites

Yes, I have the skunk path enabled, which works fine locally when not running under jserve/gdbjag once I set VID_MODE to NTSC. It's just when the debugging stub code is loaded that it locks up. jdb.cof, the Jaguar-side debug stub, installs a bunch of interrupt handlers to handle faults and any other unexpected interrupts, but I can't figure out why that conflicts with your code.

 

Here's the entire diff I used to get it working under gdbjag/jserve/jdb.cof:

diff --git a/exp/gpufire256/gpufire256.S b/exp/gpufire256/gpufire256.S
index c5ad409..0fe2e12 100644
--- a/exp/gpufire256/gpufire256.S
+++ b/exp/gpufire256/gpufire256.S
@@ -14,7 +14,7 @@ ScreenMode    EQU RGB16|VIDEN|PWIDTH4|BGEN|CSYNC
 PAL            EQU 1
 NTSC           EQU 2
 
-VID_MODE       EQU PAL
+VID_MODE       EQU NTSC
 
 ;; THESE ARE THE NTSC DEFINITIONS
 ntsc_width     = 1409
@@ -88,8 +88,7 @@ ci1:
 ;;; --------------------
        lea     my_irq(pc),a0
        move.l  a0,$0100.w
-       move.l  #$1f01<<16,d6
-       move.l  d6,$E0(a5)
+       move.w  #$1,INT1
 ;;; --------------------
 ;;; Start GPU
 ;;; --------------------
@@ -122,7 +121,8 @@ wait:
 ;;      IRQ      *
 my_irq:
        bsr.s   CopyOBL
-       move.l  d6,$E0(a5)
+       move.w  #$101,INT1
+       move.w  #$0,INT2
        rte
 
 CopyOBL:

 

Link to comment
Share on other sites

Can you try changing order of writes in at the end of my_irq?

"move.l" may write low word first.

 

Oh, I see you only acknowledge the VI, maybe writing $1f01 will also make it hang.

Edited by 42bs
Link to comment
Share on other sites

  • 2 weeks later...
On 7/7/2022 at 9:16 PM, cubanismo said:

Ever read the old threads about how awesome Alpine board debugging was compared to everything else? I do. I got a chance to play with an Alpine board recently, and yeah, the tools are pretty cool compared to the skunkCONSOLEWRITE debugging and hand-rolled instrumentation I usually rely on. However, they require the incredibly rare Alpine hardware, and an ancient PC running an ancient OS or some tricks to get the old 1995 WDB or RDBJAG tools to run, so it's not helping that many people these days. I'll post more about my romp through Alpine land later,

 

Whenever you get time we'd enjoy hearing about this. How did you run into one. What setup you used. Why did you find it unstable etc.

Link to comment
Share on other sites

On 7/11/2022 at 11:05 AM, 42bs said:

Can you try changing order of writes in at the end of my_irq?

"move.l" may write low word first.

 

Oh, I see you only acknowledge the VI, maybe writing $1f01 will also make it hang.

I don't know what was going on before. I rebuilt this and ran it without modification today, and it works fine. Nevermind this unless I can figure out how to reproduce the issue again and diagnose further.

 

9 hours ago, JagChris said:

Whenever you get time we'd enjoy hearing about this. How did you run into one. What setup you used. Why did you find it unstable etc.

Yes, I'm doing an extensive write-up on this, so much so that it wouldn't be right to dump it all in a forum post. I'll have a several-part webpage up on the whole thing in my usual half narrative/half technical content style. Stay tuned!

 

  • Thanks 1
Link to comment
Share on other sites

1 hour ago, cubanismo said:

I don't know what was going on before. I rebuilt this and ran it without modification today, and it works fine. Nevermind this unless I can figure out how to reproduce the issue again and diagnose further.

Strange, yes. But I learned the hard way, that it is good to turn off the Jaguar for a minute or so  from time to time esp. if things run weird.

  • Like 1
Link to comment
Share on other sites

I've posted my patches to enable source-level debugging support in RMAC and RLN:

 

http://jlhconsulting.gotdns.com/bugs/show_bug.cgi?id=206

http://jlhconsulting.gotdns.com/bugs/show_bug.cgi?id=207

 

This makes gdbjag a lot more useful, because now you can use it with the modern toolchain rather than resorting to DosBox/kinda hacky support on modern Linux kernels required by MADMAC/ALN. Enjoy, and let me know if you find any bugs. With these patches, RMAC and RLN also generate binaries compatible the Alpine tools (WDB and RDBJAG), so you can ditch MADMAC/ALN even when working with one of those bad-boys now.

 

The code changes for RMAC were a chunk of work, but the RLN support was about 95% there already, just commented out. I'm not clear why. It worked as-is in most cases without modification once enabled.

 

From what I can tell, this was also one of, if not the last useful features of MADMAC/ALN missing from RMAC/RLN. One more nail in the coffin once these are merged. Hopefully no one is still hoping for revived non-PRG/GEMDOS executable Alcyon object file output from RMAC or Mark Williams object file consumption in RLN. Even I haven't dreamed up uses for those.

  • Like 3
Link to comment
Share on other sites

4 hours ago, rayr said:

This is great stuff. Your hard work is impressive and I appreciate your passion and dedication. Thank you so much.

Thank you very much. It's always nice to be appreciated!

 

4 hours ago, rayr said:

Where can I donate??

While I appreciate the offer, I'm not interested in direct compensation for this work. It is supported indirectly by everyone who purchased or purchases a purple Skunkboard, not that those are terribly profitable. However, I'm not trying to limit this work to my boards or anything. It's also my way of contributing something back to the community, and especially to the people who developed and/or dug up and released all the tools, mods, documentation, etc. that I utilized in this work.

  • Like 2
Link to comment
Share on other sites

5 hours ago, dilinger said:

Thank you for sharing; to make it works, I have used WSL (Linux on Windows).

Glad to hear it works under WSL! Did you have to do anything special to get access to the USB devices in WSL?

 

5 hours ago, dilinger said:

Do you plan to add the jdb.cof source code? I remember it was available in the skunkboard source code package.

 

Yes I do. I hadn't changed it for the initial release so I didn't bother, but I have pending changes that move jdb.cof lower in memory, build it with RMAC/RLN, etc., so I'll add my version to my jserve repo on GitHub soon.

 

Ultimately I'm thinking the right direction is to merge jserve's functionality into JCP, since there's a lot of overlap (jserve has a function called "jcp()" that is essentially a kinda broken almost minimal copy of the real JCP, which it uses to upload jdb.cof at startup time). Hopefully I'll find time to tackle that before my codesigning certificates expire again ?

 

 

Link to comment
Share on other sites

I have just built the sdk toolchain and not yet tested it with my console/Skunkboard. Other than, I do not recall problems to access to USB devices.

About jcp, I did a jcp2 version many years ago to add some features. It was done to pilot more than one console connected to a PC.

 

ELF binary format support
64bits support
Communication timeout parameter
USB port selection
Bus and Port selections
Skunkboard serial number selection
Libusb 1.0.x support

 

I may check if a merge is possible to your jcp and propose a PR in the future.

  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...