USB device stack, with KL25Z fixes for USB 3.0 hosts and sleep/resume interrupt handling

Dependents:   frdm_Slider_Keyboard idd_hw2_figlax_PanType idd_hw2_appachu_finger_chording idd_hw3_AngieWangAntonioDeLimaFernandesDanielLim_BladeSymphony ... more

Fork of USBDevice by mbed official

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

Update - 2/15/2016

My recent fixes introduced a new problem that made the initial connection fail most of the time on certain hosts. It's not clear if the common thread was a particular type of motherboard or USB chip set, or a specific version of Windows, or what, but several people ran into it. We tracked the problem down to the "stall" fixes in the earlier updates, which we now know weren't quite the right fixes after all. The latest update (2/15/2016) fixes this. It has new and improved "unstall" handling that so far works well with diverse hosts.

Race conditions and overall stability

The base mbed KL25Z implementation has a lot of problems with "race conditions" - timing problems that can happen when hardware interrupts occur at inopportune moments. The library shares a bunch of static variable data between interrupt handler context and regular application context. This isn't automatically a bad thing, but it does require careful coordination to make sure that the interrupt handler doesn't corrupt data that the other code was in the middle of updating when an interrupt occurs. The base mbed code, though, doesn't do any of the necessary coordination. This makes it kind of amazing that the base code worked at all for anyone, but I guess the interrupt rate is low enough in most applications that the glitch rate was below anyone's threshold to seriously investigate.

This overhaul adds the necessary coordination for the interrupt handlers to protect against these data corruptions. I think it's very solid now, and hopefully entirely free of the numerous race conditions in the old code. It's always hard to be certain that you've fixed every possible bug like this because they strike (effectively) at random, but I'm pretty confident: my test application was reliably able to trigger glitches in the base code in a matter of minutes, but the same application (with the overhauled library) now runs for days on end without dropping the connection.

Stalled endpoint fixes

USB has a standard way of handling communications errors called a "stall", which basically puts the connection into an error mode to let both sides know that they need to reset their internal states and sync up again. The original mbed version of the USB device library doesn't seem to have the necessary code to recover from this condition properly. The KL25Z hardware does some of the work, but it also seems to require the software to take some steps to "un-stall" the connection. (I keep saying "seems to" because the hardware reference material is very sketchy about all of this. Most of what I've figured out is from observing the device in action with a Windows host.) This new version adds code to do the necessary re-syncing and get the connection going again, automatically, and transparently to the user.

USB 3.0 Hosts

The original mbed code sometimes didn't work when connecting to hosts with USB 3.0 ports. This didn't affect every host, but it affected many of them. The common element seemed to be the Intel Haswell chip set on the host, but there may be other chip sets affected as well. In any case, the problem affected many PCs from the Windows 7 and 8 generation, as well as many Macs. It was possible to work around the problem by avoiding USB 3.0 ports - you could use a USB 2 port on the host, or plug a USB 2 hub between the host and device. But I wanted to just fix the problem and eliminate the need for such workarounds. This modified version of the library has such a fix, which so far has worked for everyone who's tried.

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 allocates twice as much memory for USB buffers as it really needed to. It looks like the original developers intended to implement the KL25Z USB hardware's built-in double-buffering mechanism, but they ultimately abandoned that effort. But they left in the double memory allocation. This version removes that and allocates only what's actually needed. The USB buffers aren't that big (128 bytes per endpoint), so this doesn't save a ton of memory, but even a little memory is pretty precious on this machine given that it only has 16K.

(I did look into adding the double-buffering support that the original developers abandoned, but after some experimentation I decided they were right to skip it. It just doesn't seem to mesh well with the design of the rest of the mbed USB code. I think it would take a major rewrite to make it work, and it doesn't seem worth the effort given that most applications don't need it - it would only benefit applications that are moving so much data through USB that they're pushing the limits of the CPU. And even for those, I think it would be a lot simpler to build a purely software-based buffer rotation mechanism.)

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). I fixed the misnomers and added symbolic names for formerly anonymous numbers. Hopefully the next person who has to overhaul this code will at least have an easier time understanding what I thought I was doing!

Committer:
mjr
Date:
Fri Mar 17 22:01:47 2017 +0000
Revision:
54:2e181d51495a
Parent:
25:7c72828865f3
Comments

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 16:4f6df64750bd 1 /**
mbed_official 16:4f6df64750bd 2 ******************************************************************************
mbed_official 16:4f6df64750bd 3 * @file usb_regs.h
mbed_official 16:4f6df64750bd 4 * @author MCD Application Team
mbed_official 16:4f6df64750bd 5 * @version V2.1.0
mbed_official 16:4f6df64750bd 6 * @date 19-March-2012
mbed_official 16:4f6df64750bd 7 * @brief hardware registers
mbed_official 16:4f6df64750bd 8 ******************************************************************************
mbed_official 16:4f6df64750bd 9 * @attention
mbed_official 16:4f6df64750bd 10 *
mbed_official 16:4f6df64750bd 11 * <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
mbed_official 16:4f6df64750bd 12 *
mbed_official 16:4f6df64750bd 13 * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
mbed_official 16:4f6df64750bd 14 * You may not use this file except in compliance with the License.
mbed_official 16:4f6df64750bd 15 * You may obtain a copy of the License at:
mbed_official 16:4f6df64750bd 16 *
mbed_official 16:4f6df64750bd 17 * http://www.st.com/software_license_agreement_liberty_v2
mbed_official 16:4f6df64750bd 18 *
mbed_official 25:7c72828865f3 19 * Unless required by applicable law or agreed to in writing, software
mbed_official 25:7c72828865f3 20 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 16:4f6df64750bd 21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 16:4f6df64750bd 22 * See the License for the specific language governing permissions and
mbed_official 16:4f6df64750bd 23 * limitations under the License.
mbed_official 16:4f6df64750bd 24 *
mbed_official 16:4f6df64750bd 25 ******************************************************************************
mbed_official 16:4f6df64750bd 26 */
mbed_official 16:4f6df64750bd 27
mbed_official 16:4f6df64750bd 28 #ifndef __USB_OTG_REGS_H__
mbed_official 16:4f6df64750bd 29 #define __USB_OTG_REGS_H__
mbed_official 16:4f6df64750bd 30
mbed_official 16:4f6df64750bd 31 typedef struct //000h
mbed_official 16:4f6df64750bd 32 {
mbed_official 16:4f6df64750bd 33 __IO uint32_t GOTGCTL; /* USB_OTG Control and Status Register 000h*/
mbed_official 16:4f6df64750bd 34 __IO uint32_t GOTGINT; /* USB_OTG Interrupt Register 004h*/
mbed_official 16:4f6df64750bd 35 __IO uint32_t GAHBCFG; /* Core AHB Configuration Register 008h*/
mbed_official 16:4f6df64750bd 36 __IO uint32_t GUSBCFG; /* Core USB Configuration Register 00Ch*/
mbed_official 16:4f6df64750bd 37 __IO uint32_t GRSTCTL; /* Core Reset Register 010h*/
mbed_official 16:4f6df64750bd 38 __IO uint32_t GINTSTS; /* Core Interrupt Register 014h*/
mbed_official 16:4f6df64750bd 39 __IO uint32_t GINTMSK; /* Core Interrupt Mask Register 018h*/
mbed_official 16:4f6df64750bd 40 __IO uint32_t GRXSTSR; /* Receive Sts Q Read Register 01Ch*/
mbed_official 16:4f6df64750bd 41 __IO uint32_t GRXSTSP; /* Receive Sts Q Read & POP Register 020h*/
mbed_official 16:4f6df64750bd 42 __IO uint32_t GRXFSIZ; /* Receive FIFO Size Register 024h*/
mbed_official 16:4f6df64750bd 43 __IO uint32_t DIEPTXF0_HNPTXFSIZ; /* EP0 / Non Periodic Tx FIFO Size Register 028h*/
mbed_official 16:4f6df64750bd 44 __IO uint32_t HNPTXSTS; /* Non Periodic Tx FIFO/Queue Sts reg 02Ch*/
mbed_official 16:4f6df64750bd 45 uint32_t Reserved30[2]; /* Reserved 030h*/
mbed_official 16:4f6df64750bd 46 __IO uint32_t GCCFG; /* General Purpose IO Register 038h*/
mbed_official 16:4f6df64750bd 47 __IO uint32_t CID; /* User ID Register 03Ch*/
mbed_official 16:4f6df64750bd 48 uint32_t Reserved40[48]; /* Reserved 040h-0FFh*/
mbed_official 16:4f6df64750bd 49 __IO uint32_t HPTXFSIZ; /* Host Periodic Tx FIFO Size Reg 100h*/
mbed_official 16:4f6df64750bd 50 __IO uint32_t DIEPTXF[3];/* dev Periodic Transmit FIFO */
mbed_official 16:4f6df64750bd 51 }
mbed_official 16:4f6df64750bd 52 USB_OTG_GREGS;
mbed_official 16:4f6df64750bd 53
mbed_official 16:4f6df64750bd 54 typedef struct // 800h
mbed_official 16:4f6df64750bd 55 {
mbed_official 16:4f6df64750bd 56 __IO uint32_t DCFG; /* dev Configuration Register 800h*/
mbed_official 16:4f6df64750bd 57 __IO uint32_t DCTL; /* dev Control Register 804h*/
mbed_official 16:4f6df64750bd 58 __IO uint32_t DSTS; /* dev Status Register (RO) 808h*/
mbed_official 16:4f6df64750bd 59 uint32_t Reserved0C; /* Reserved 80Ch*/
mbed_official 16:4f6df64750bd 60 __IO uint32_t DIEPMSK; /* dev IN Endpoint Mask 810h*/
mbed_official 16:4f6df64750bd 61 __IO uint32_t DOEPMSK; /* dev OUT Endpoint Mask 814h*/
mbed_official 16:4f6df64750bd 62 __IO uint32_t DAINT; /* dev All Endpoints Itr Reg 818h*/
mbed_official 16:4f6df64750bd 63 __IO uint32_t DAINTMSK; /* dev All Endpoints Itr Mask 81Ch*/
mbed_official 16:4f6df64750bd 64 uint32_t Reserved20; /* Reserved 820h*/
mbed_official 16:4f6df64750bd 65 uint32_t Reserved9; /* Reserved 824h*/
mbed_official 16:4f6df64750bd 66 __IO uint32_t DVBUSDIS; /* dev VBUS discharge Register 828h*/
mbed_official 16:4f6df64750bd 67 __IO uint32_t DVBUSPULSE; /* dev VBUS Pulse Register 82Ch*/
mbed_official 16:4f6df64750bd 68 __IO uint32_t DTHRCTL; /* dev thr 830h*/
mbed_official 16:4f6df64750bd 69 __IO uint32_t DIEPEMPMSK; /* dev empty msk 834h*/
mbed_official 16:4f6df64750bd 70 }
mbed_official 16:4f6df64750bd 71 USB_OTG_DREGS;
mbed_official 16:4f6df64750bd 72
mbed_official 25:7c72828865f3 73 typedef struct
mbed_official 16:4f6df64750bd 74 {
mbed_official 16:4f6df64750bd 75 __IO uint32_t DIEPCTL; /* dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/
mbed_official 16:4f6df64750bd 76 uint32_t Reserved04; /* Reserved 900h + (ep_num * 20h) + 04h*/
mbed_official 16:4f6df64750bd 77 __IO uint32_t DIEPINT; /* dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h*/
mbed_official 16:4f6df64750bd 78 uint32_t Reserved0C; /* Reserved 900h + (ep_num * 20h) + 0Ch*/
mbed_official 16:4f6df64750bd 79 __IO uint32_t DIEPTSIZ; /* IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h*/
mbed_official 16:4f6df64750bd 80 uint32_t Reserved14;
mbed_official 16:4f6df64750bd 81 __IO uint32_t DTXFSTS;/*IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/
mbed_official 16:4f6df64750bd 82 uint32_t Reserved1C; /* Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/
mbed_official 16:4f6df64750bd 83 }
mbed_official 16:4f6df64750bd 84 USB_OTG_INEPREGS;
mbed_official 16:4f6df64750bd 85
mbed_official 25:7c72828865f3 86 typedef struct
mbed_official 16:4f6df64750bd 87 {
mbed_official 16:4f6df64750bd 88 __IO uint32_t DOEPCTL; /* dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/
mbed_official 16:4f6df64750bd 89 uint32_t Reserved04; /* Reserved B00h + (ep_num * 20h) + 04h*/
mbed_official 16:4f6df64750bd 90 __IO uint32_t DOEPINT; /* dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h*/
mbed_official 16:4f6df64750bd 91 uint32_t Reserved0C; /* Reserved B00h + (ep_num * 20h) + 0Ch*/
mbed_official 16:4f6df64750bd 92 __IO uint32_t DOEPTSIZ; /* dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h*/
mbed_official 16:4f6df64750bd 93 uint32_t Reserved14[3];
mbed_official 16:4f6df64750bd 94 }
mbed_official 16:4f6df64750bd 95 USB_OTG_OUTEPREGS;
mbed_official 16:4f6df64750bd 96
mbed_official 16:4f6df64750bd 97 typedef struct
mbed_official 16:4f6df64750bd 98 {
mbed_official 16:4f6df64750bd 99 __IO uint32_t HCFG; /* Host Configuration Register 400h*/
mbed_official 16:4f6df64750bd 100 __IO uint32_t HFIR; /* Host Frame Interval Register 404h*/
mbed_official 16:4f6df64750bd 101 __IO uint32_t HFNUM; /* Host Frame Nbr/Frame Remaining 408h*/
mbed_official 16:4f6df64750bd 102 uint32_t Reserved40C; /* Reserved 40Ch*/
mbed_official 16:4f6df64750bd 103 __IO uint32_t HPTXSTS; /* Host Periodic Tx FIFO/ Queue Status 410h*/
mbed_official 16:4f6df64750bd 104 __IO uint32_t HAINT; /* Host All Channels Interrupt Register 414h*/
mbed_official 16:4f6df64750bd 105 __IO uint32_t HAINTMSK; /* Host All Channels Interrupt Mask 418h*/
mbed_official 16:4f6df64750bd 106 }
mbed_official 16:4f6df64750bd 107 USB_OTG_HREGS;
mbed_official 16:4f6df64750bd 108
mbed_official 16:4f6df64750bd 109 typedef struct
mbed_official 16:4f6df64750bd 110 {
mbed_official 16:4f6df64750bd 111 __IO uint32_t HCCHAR;
mbed_official 16:4f6df64750bd 112 __IO uint32_t HCSPLT;
mbed_official 16:4f6df64750bd 113 __IO uint32_t HCINT;
mbed_official 16:4f6df64750bd 114 __IO uint32_t HCINTMSK;
mbed_official 16:4f6df64750bd 115 __IO uint32_t HCTSIZ;
mbed_official 16:4f6df64750bd 116 uint32_t Reserved[3];
mbed_official 16:4f6df64750bd 117 }
mbed_official 16:4f6df64750bd 118 USB_OTG_HC_REGS;
mbed_official 16:4f6df64750bd 119
mbed_official 25:7c72828865f3 120 typedef struct
mbed_official 16:4f6df64750bd 121 {
mbed_official 16:4f6df64750bd 122 USB_OTG_GREGS GREGS;
mbed_official 16:4f6df64750bd 123 uint32_t RESERVED0[188];
mbed_official 16:4f6df64750bd 124 USB_OTG_HREGS HREGS;
mbed_official 16:4f6df64750bd 125 uint32_t RESERVED1[9];
mbed_official 16:4f6df64750bd 126 __IO uint32_t HPRT;
mbed_official 16:4f6df64750bd 127 uint32_t RESERVED2[47];
mbed_official 16:4f6df64750bd 128 USB_OTG_HC_REGS HC_REGS[8];
mbed_official 16:4f6df64750bd 129 uint32_t RESERVED3[128];
mbed_official 16:4f6df64750bd 130 USB_OTG_DREGS DREGS;
mbed_official 16:4f6df64750bd 131 uint32_t RESERVED4[50];
mbed_official 16:4f6df64750bd 132 USB_OTG_INEPREGS INEP_REGS[4];
mbed_official 16:4f6df64750bd 133 uint32_t RESERVED5[96];
mbed_official 16:4f6df64750bd 134 USB_OTG_OUTEPREGS OUTEP_REGS[4];
mbed_official 16:4f6df64750bd 135 uint32_t RESERVED6[160];
mbed_official 16:4f6df64750bd 136 __IO uint32_t PCGCCTL;
mbed_official 16:4f6df64750bd 137 uint32_t RESERVED7[127];
mbed_official 16:4f6df64750bd 138 __IO uint32_t FIFO[4][1024];
mbed_official 16:4f6df64750bd 139 }
mbed_official 16:4f6df64750bd 140 USB_OTG_CORE_REGS;
mbed_official 16:4f6df64750bd 141
mbed_official 16:4f6df64750bd 142
mbed_official 16:4f6df64750bd 143 #define OTG_FS_BASE (AHB2PERIPH_BASE + 0x0000)
mbed_official 16:4f6df64750bd 144 #define OTG_FS ((USB_OTG_CORE_REGS *) OTG_FS_BASE)
mbed_official 16:4f6df64750bd 145
mbed_official 16:4f6df64750bd 146 #endif //__USB_OTG_REGS_H__
mbed_official 16:4f6df64750bd 147
mbed_official 16:4f6df64750bd 148 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
mbed_official 16:4f6df64750bd 149