Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: frdm_Slider_Keyboard idd_hw2_figlax_PanType idd_hw2_appachu_finger_chording idd_hw3_AngieWangAntonioDeLimaFernandesDanielLim_BladeSymphony ... more
Fork of USBDevice by
You are viewing an older revision! See the latest version
Homepage
This is an overhauled version of the standard mbed USB device-side driver library, with bug fixes for KL25Z devices. It greatly improves reliability and stability of USB on the KL25Z, especially with devices using multiple endpoints concurrently.
I've had some nagging problems with the base mbed implementation for a long time, manifesting as occasional random disconnects that required rebooting the device. Recently (late 2015), I started implementing a USB device on the KL25Z that used multiple endpoints, and suddenly the nagging, occasional problems turned into frequent and predictable crashes. This forced me to delve into the USB stack and figure out what was really going on. Happily, the frequent crashes made it possible to track down and fix the problems. This new version is working very reliably in my testing - the random disconnects seem completely eradicated, even under very stressful conditions for the device.
Summary¶
- Overall stability improvements
- USB 3.0 host support
- Stalled endpoint fixes
- Sleep/resume notifications
- Smaller memory footprint
- General code cleanup
Race conditions and overall stability¶
The base mbed KL25Z implementation has a lot of problems with race conditions. The code handles some processing in ISR context and some in the normal application context (non-ISR), and shares a bunch of static variable state between the two contexts. There are some obvious test-and-set type race conditions (e.g., the read-and-update bit mask access to Data1 and epComplete), and some more subtle conditions involving order of access to multiple variables (e.g., giving ownership of a BDT block to the hardware before setting up all of the fields, or before changing related internal state variables). After spending some time with the code and seeing how many clear concurrency errors it has, it became rather amazing that it ever worked at all, but I guess the probabilities were low enough in low-bandwidth applications that most people could live with it, and everyone chalked up their random disconnects to gremlins.
This overhaul has some design changes that improve the basic concurrency strategy so that there's less contention to start with, and then adds protection for critical sections to ensure serialized access to shared variables and shared state. It's always hard to be certain from code inspection that you've eliminated every possible concurrency error, because they can be extremely subtle, but I've definitely eliminated a lot of them. You can never even be certain from testing, since these types of errors are probabilistic, but I'm pretty confident. My test setup was able to trigger failures in the old code in a matter of minutes, and the new code will run for days under the same conditions and never drop a connection.
Stalled endpoint fixes¶
The base mbed version doesn't perform the necessary steps with the SIE hardware to un-stall an endpoint. This makes a stalled endpoint an unrecoverable condition with the base library; you basically have to reset the device to re-establish the connection if a stall should occur. Endpoint stalls seem uncommon in practice, but they're a well-defined part of the USB protocol and do occur from time to time, due to communications errors at the hardware level, timing anomalies, etc. This might have been another source of the intermittent disconnects I used to see, so this should also improve overall connection stability.
USB 3.0 Hosts¶
I've seen several reports on the Web about problems with the mbed USB client stack running on the KL25Z when connecting to hosts with USB 3.0 ports. I've observed the problem on two separate Windows machines (running Win 7 and Win 8.1), and it also reportedly affects some Macs. I haven't narrowed down the exact conditions that cause the problem, but one suggestion is that the common element is Intel Haswell chip set hardware. If that's the case it probably affects a lot of Win 7/8 generation PCs.
The problem can be worked around by using USB 2.0 ports or connecting a USB 2 hub between the device and host, but I wanted to fix it at the software level if possible.
I tracked down the problem to a timing issue that seems to cause the device and host to get out of sync with respect to flow direction on the USB connection during the initial handshake. It seems that the host can issue a CONTROL OUT token (this means that the host sends a control packet to the device, as part of the exchange of configuration data during the connection handshake) at a point where the client is trying to send the response for a previous CONTROL IN token (which means that the host is ready to receive a control packet from the client). I found a note in some USB 3.0 reference material that this situation can occur, and that the client can resolve it by sending a zero-length ACK, which tells the host that the client isn't ready and that the host request should be repeated. In this forked version, I added a little code to do just this. The fix seems a little hack-ish, but it does seem to have resolved the problem for my own setup, and I've heard from other people that it works for them as well.
Sleep/resume notifications¶
This modified version also contains an innocuous change to the KL25Z USB HAL code to handle sleep and resume interrupts with calls to suspendStateChanged(). The original KL25Z code omitted these calls (and in fact didn't even enable the interrupts), but I think this was an unintentional oversight - the notifier function is part of the generic API, and other supported boards all implement it. I use this feature in my own application so that I can distinguish sleep mode from actual disconnects and handle the two conditions correctly.
Smaller memory footprint¶
The base mbed version of the code incorrectly allocates twice as much memory for endpoint buffers as is needed. I suspect this is because the original developers intended to exploit the KL25Z SIE hardware's native double-buffering mechanism, but they never implemented that feature, so the extra memory allocation is unnecessary and wasteful. This version allocates only what's actually needed. (I did look into adding the double-buffering support, but after some experimentation decided that it wouldn't fit into the current design and would really require a full rewrite, which is beyond what I want to tackle right now. Double buffering would only benefit high-bandwidth applications that push the limits of the CPU, which probably isn't common among KL25Z applications. And even then it would probably be easier to implement a software buffer rotation mechanism instead; the SIE's native scheme seems difficult to work with due to hidden state in the hardware that the software has to keep up with.)
General code cleanup¶
The KL25Z HAL code in this version has greatly expanded commentary and a lot of general cleanup. Some of the hardware constants were given the wrong symbolic names (e.g., EVEN and ODD were reversed), and many were just missing (written as hard-coded numbers without explanation). Hopefully the next person who has to overhaul this code when they discover how woefully inadequate and broken my version is will at least have an easier time understanding what I thought I was doing!!!
