Close

​Tool Everything Tool Terrible Two: OpenOCD Rift

A project log for HP 82240B IR Receiver and Printer Interface

This is an IR receiver and interface for adapting a commodity receipt printer to be 82240B-compatible.

ziggurat29ziggurat29 07/05/2017 at 17:440 Comments

Summary:

Did I ever mention how much I dislike Eclipse in particular and Java in general? Well, I guess I just did.

Deets:

OK, today, spontaneously, my debugger fails to run. I now get the dreaded "Error in final launch sequence" message. 'Details' reveals "The system tried to join a drive to a directory on a joined drive."

"Joining drives", WTF? This error is a Windows error, 138 (0x8A) ERROR_JOIN_TO_JOIN, and the message comes from using FormatMessage to translate a GetLastError() result into some friendly text. Veteran Windows programmers will already know that you have to take these things with a grain of salt, because you are hoping that the programmer did a SetLastError() with a sane and meaningful value -- there's nothing that enforces that sanity. Also, sometimes between where an error occurs, and where you get around to doing a GetLastError(), there is enough intervening code that the error value no longer reflects that generated by the root cause. Anyway, I thought I'd give a brief mention about this particular error code in this particular instance.

First, what does it mean? The literal text refers to an ancient facility from DOS whereby you can 'JOIN' a drive onto a directory of another drive's filesystem. It's a little like mount'ing in *nix. I have never seen anyone use this facility in over 30 years. Presumably it was to extend storage by, say, JOIN'ing a whole 'nuther floppy onto a directory that some application used for data storage. Whatever it was for, the facility (along with SUBST) still exists to this day in the NT-derivatives (though implemented differently). Microsoft does like their backwards compatibility.

So why are we getting it here? Well, that is Java's fault. An error occurs within Java's Windows platform-specific implementation, and that implementation chooses to simply do a GetLastError() FormatMessage() and bubble the results up. A much better implementation of Java would have been for it to have said something about what Java was attempting to do when the error occurred, because I can tell you it certainly wasn't trying 'to JOIN a drive to a directory on a joined drive'! Years ago, I did debug into Java to find where it originated for an unrelated reason, but I can't recall exactly where, alas, so you'll have to take my word on that. Or not; your choice.

Anyway, as a result of all this, googling on that message typically will not give you useful results because this comes up in many unrelated products, and arises from many unrelated causes. I can tell you that in this case, what is happening is that the openocd.exe process is terminating unexpectedly, causing the pipe to be broken, and other stuff (gdb) to lose connection to the localhost port on which it is listening (3333 in this case). You can see it here:

In the 'Debug' tab, you can see "<terminated, exit value: 0> openocd" with the red stop icon, and the GDB process is still running below it. Exit value 0. Hmm, that usually means 'normal termination'. Who knows, though, that's up to the programmer to be meaningful as well, and a lot of folks don't set the process return value to distinctive things. But it definitely terminated for one reason or another, and that certainly would bring debugging to an end, since openocd is what interfaces with the ST-Link v2.1 pod.

So, what to do. Well, you'll have to dig into Eclipse for that, or more properly, the AC6 plugin to Eclipse that is what is doing all this launching stuff. Not thanks. Here is my work-around; it's a little klunky, but at least it does work.

Work Around for Can't Launch OpenOCD Joined Drive Nonsense

What we will do is create an 'external tool', and manually launch that, and just leave it running. This will be our manually launched OpenOCD instance. It's a little klunky, because the joys of our IDE automatically launching stuff will be over, and also because as it turns out, the configuration will be project specific, so you'll need to twiddle with it if you work on multiple projects at once. More details about that later. First, creating the external tool.

Under Run, External Tools, External Tools Configurations... create a 'New launch configuration'. There is an icon in the upper left, it looks like a page with a "+" sign on it. Do that, and give it some helpfull name like "ICantBelieveIActuallyHaveToRunThis". For reasons of space in this example I used the more pedestrian "OpenOCDforBluePill". Tip: do not use spaces in the name, or you will never be able to access it, or ever be able to delete it. So be careful with that axe, Eugene.

On the 'main' tab, you will need to specify the 'Location' of the openocd.exe, the 'Working Directory' where that process is launched, so it can find it's data, and the 'Arguments' that are passed on the command line for the process. Here is what mine looks like:

I have only ever gotten this to work with absolute paths, not of the fancy 'Variables...' seem to have any effect. Consequently, this External Tool is bound to the version of System Workbench I have currently installed (via 'Location' and 'Working Directory') and also this particular project (by 'Arguments'). Sigh. But, I do now have a working environment, so there's a good thing!

OK, how to use:

Before you start debugging, you will need to run the External Tool from the Run, External Tools flyout menu. This will stimulate a build first just because, then you will see OpenOCD process running, with the green icon.

Then, when you are ready to debug, just the 'bug' button as per usual. This will attempt to launch a separate openocd.exe, which will die, but the gdb will connect instead to your manually started one, and you will be off to the races once again. Note: you might or might not get a new message box complaining about the second openocd having croaked. Just dismiss it. It can't run successfully because the localhost port 3333 is already being used by the other successfully running process.

An upshot is that you will be able to see the openocd console output, so you can see more info about why it's croaking, if it does still croak on you.

OK, now back to work on serial port stuff....

Next:

Now I am working once again, so I can proceed. Again.

Discussions