This blog post might seem commercial… but I have no connection to TotalPhase. I’ve used their Beagle 480 USB analyser for some time, and before that have used a variety of other solutions (mostly SW-based), so have some idea what other options are out there.
It’s worth noting that they seem to give free updates forever. When I first used the Beagle 480 it could dissect mass storage & HID I think. Since then they’ve added almost every class possible… hell you can even do stuff like sniff a USB-Ethernet device, and pass the frames to Wireshark for IP-layer decoding. Total Phase has added tons of features in the last 4-5 years I’ve used this device, and they’ve all been freely available and usable with my device.
So why do I think other debuggers are a waste of time? Simply: the ability to trigger in/out of the device. Check out this video for more:
I also wrote about some of this in an article in Circuit Cellar, see The CC Webstore if you want to check that out, but the part I talk about debugging with the 480 is only a few paragraphs.
Basically you can do stuff like the following:
Trigger a Debugger from Specific USB Packets
This is a huge one for me, or any firmware developer. When debugging USB you cannot pause an embedded target, as it will stop responding to USB requests, and then cause it to kill the connection. So when you need to setup breakpoints you can sometimes do it quickly (e.g.: pause target, dump a value, and continue running before USB errors out), or you need to be selective with where breakpoints happen.
Much of the time when debugging USB errors you can see the error on the bus, but you don’t know WHERE in the code the error is coming from, or you would have fixed it already.
You can setup pretty advanced data matching in the TotalPhase Data Center Software, such as matching specific packet types (including corrupted) or even specific data, all in real-time:
This trigger can be fed into the emulator to cause a BREAK condition. This can be done by adding an interrupt into your system with a breakpoint in it, although maybe your ICE has some sort of ‘external break trigger’, but none of mine do. Anyway this means you get a breakpoint right when some data goes over the bus to see what’s happening – did you just do a memcpy() that is overwriting some buffer before the system was done sending it?
Trigger Scope from Specific USB Packets / Errors
Other issues might be at the hardware layer. Previously I had to troubleshoot some random USB errors that only occurred when the interface was going full speed, not when only a few packets were going over.
Using the ‘trigger on error packet’ output I could see what was happening in the analog domain during these errors. Turns out the PCB designer had put a great big split GND plane (see my Blog Post) inbetween the signals the USB chip / FPGA interface. The huge ground bounce was visible during these errors.
Monitor status of tasks in running system
The Beagle 480 has a bunch of possible inputs (unfortunately the USB 3.0 version seems to only have 1 input & 1 output). You can toggle IO pins from inside the firmware when specific tasks start & end – for example assign 1 pin to the low-level USB task, 1 pin to the higher-level class, and 1 pin to the user software. By monitoring the status of the pin toggles in the Data Center software, it’s pretty easy to catch a problem such as a task stops running properly.
I’ve used this technique fairly regularly to get an idea of what my USB code is doing when it needs to pass messages between multiple tasks. Sometimes for example your simplistic scheduler isn’t calling the final task which actually processes the data, so the system runs out of buffers faster than you expect!
Synchronize Other stuff (equipment, debuggers) to USB Capture
The idea of synchronization is pretty critical in my mind. For example say you want to reverse-engineer some USB device. You can setup hardware to trigger when it sees a specific output condition (say some sequence of packets). This trigger can be used to synchronize to the actual USB data on the bus – this will help you figure out exactly what messages are being passed.