µTasker USB Device Configuration and Keyboard Testing
The µTasker USB device support includes USB-CDC, USB-MSD and USB HID mouse and keyboard. These can however be flexibly mixed as composite devices as discussed here. The keyboard test, as built into the framework is discussed towards the botton of the page.
µTasker USB Device Configuration
The µTasker USB device operation attempts to make the configuration and use by the application as simple as possible. For overall implementation details and USB-CDC (Communication Device Class) operation see the USB User's Guide. Since the original USB-CDC class, which is possibly the most used in embedded systems, the support has been extended to include USB-MSD (Mass Storage Device) [popular for allowing PCs to work with SD card content] and USB-HID (Humand Interface Device) mouse/keyboard. The following shows the way that the relevant files are included in the application project to both keep the code very readable as well as allowing a modular solution which is hardware indendent to a very high degree.
- \uTasker\USB_drv.c - the generic USB interface that is hardware and class independent (handling enumeration, configuration and general endpoint transmission and reception).
- \Hardware\Kinetis\kinetis.c - the hardware specific layer interface including interrupt handling (eg. of Kinetis but true for all supported platforms).
- \Applications\uTaskerV1.4\usb_application.c - the application layer which implements the class details as well as any application specific stuff.
- \Applications\uTaskerV1.4\usb_cdc_descriptors.h - descriptors and other details of the class-specific configuration, which adapt themselves according to whether the class is used and whether it is a part of a composite device.
The defines used to control the main USB configuration (or composite of these) are in the config.h file associated with the application:
- #define USB_INTERFACE - enables USB support as long as the device has USB device capability.
- #define USE_USB_CDC - enables USB-CDC support, whereby the (first) interface is used as debug interface when connected but can be switched to a USB-UART bridge mode.
- #define USB_CDC_COUNT 1 - (additional option when USB-CDC is enabled) a single USB-CDC interface is used when left at 1 but by incrementing this additional USB-CDC interfaces are added, each connected to a UART (up to the maximum UARTs available in the hardware).
- #define USE_USB_MSD - enables USB-SUPPORT support, whereby also SDCARD_SUPPORT needs to be enabled for it to operate with an SD card. When FLASH_FAT is enabled it works with the internal Flash of the device as a hard drive. Both SD card and internal Flash can be enabled at the same time and the USB-MSD device appears as two external hardware drives to the USB host.
- #define USE_USB_HID_MOUSE - enables USB-HID mouse support - how the mouse input is controlled is hardware specific but typical methods are by controlling its co-ordiates with readings from an accelerometer clicks controlled by input GPIO states.
- #define USE_USB_HID_KEYBOARD - enables USB-HID keyboard support - a keyboard method built into the framework is described later on this page.
The above defines can be enabled individually when ony one class is required or can be mixed as desired. For example, a USB device with 3 USB-CDC interfaces, USB-MSD with SD card and also keyboard operation could be configured by simply enabling the following defines:
#define USB_CDC_COUNT 3
For this to be possible, the following interface strategy is used, whereby it is to be noted that a USB driver is required when there is a USB-CDC interface involved but not if only HID or MSD classes are enabled. The µTasker project includes USB drivers for 1, 2, 3,4, 5 and 6 USB-CDC interfaces for 32 and 64 bit Windows. A USB-CDC driver declaring more USB-CDC interfaces than used is adequate when not mixed with other classes (eg. the driver for 6 USB-CDC interfaces can in fact be used for 1..6 interfaces when only USB-CDC is available) but as soon as mixed with other classes the interface number must also be exact to avoid the USB host becoming confused. The following table shows some composite configurations, mostly containing CDC class interfaces:
|Interface||Only CDC||CDC and MSD||CDC and Mouse||CDC, MSD and keyboard||MSD, Mouse, Keyboard|
|0||CDC 0||CDC 0||CDC 0||CDC 0||MSD|
|1||CDC 1||CDC 1||CDC 1||CDC 1||HID Mouse|
|2||CDC 2||CDC 2||CDC 2||CDC 2||HID Keyboard|
|3||CDC 3||MSD||CDC 3||MSD||-|
|4||CDC 4||-||HID Mouse||HID Keyboard||-|
Notice that the USB-CDC interfaces are always the first in the configuration, followed by USB-MSD, then HID mouse and finally HID Keyboard, if available. This strategy means that it is easy to automatically number the interfaces so that the USB driver matches the USB-CDC interfaces that are present. In case there is no USB-CDC then the ordering continues with USB-MSD, HID mouse and HID keyboard. Also the driver required for each configuration is obvious, whereby a USB-CDC device with less that 6 interfaces but no other classes can in fact use the USB driver for 6 interfaces without any issues.
Testing USB Keyboard Operation
The USB-HID Keyboard can of course be used to develop a real keyboard by reporting scan codes depending on scanned keyboard inputs. It is however not envisaged that this operation is often of real interest in embedded systems but more the ability to send keyboard input sequences to a usb host will more often be used. For this reason such an application is included in the µTasker framework to allow the operation to be simply verified.
This mode is entered via the debug menu by commanding "usb-kb" in the USB menu.
USB menu =================== up go to main menu usb_errors Show USB errors usb_cnt_rst Reset USB counters usb-kb Keyboard input (disconnect to quit) help Display menu specific help quit Leave command mode
Once in the mode and the USB is connected to the USB host all debug input (this could be from a USB-CDC debug connection, Telnet or UART, depending on which connection was used to connect to the menu) is placed into a software FIFO and this FIFO is read out each time the USB HID keyboard is polled by the USB host. The result is that individual characters can be typed in at the debug input which are then passed on to the USB host as if it was originating from an external keyboard (it is to be noted that the original ASCII values are converted to USB scan codes that are recognised by the USB host since scan codes are not directly ASCII - there is a reference for USB scan codes at USB Scan Codes for usual US Layout).
More intesting is however the fact that rather than typing in individual values to the debug input it is possible to send pre-prepared sequences so that the USB host receives them as fast keyboard input. Software can of course use the same software FIFO to send similar sequences that are defined in code or read from files etc. which would be the most probable embedded requirement.
Beware when using this test of the fact that the when entering input from a terminal emulator the keyboard input will by fed back via the "keyboard" to the same terminal emulator if the USB host is the same PC. This results in it this being fed back to the debug input and thus an infinite feedback loop resulting; for this reason it is best to enter the debug input from a different source than the PC that will receive the keyboard input!
To help visualise the operation the following diagram shows the case when debug input is fed in from PC1 via UART and acts as keyboard input to PC 2:
PC 1 acting as USB keyboard to PC 2
The keyboard interrupt polling rate defines the maximum typing speed that can be obtained and its value is defined in the interrupt endpoint characteristics in the USB descriptors used during enumeration. The fastest is achieved when this is defined to be 1ms and slower polling rates of 2, 4, 8, 16, 32ms etc. may be defined instead. Assuming 1ms is used a typing speed of up to 1000 characters a second is possible, whereby it is to be noted that repeated characters that occur in the input stream slow the rate due to the fact that a key release has to be inserted between each so that they can be recognised.
In some situations the maximum input rate may be too great for host applications and so the capability to add additional inter-key delays is also foreseen. This is enabled by the define USB_KEYBOARD_DELAY when used together with USE_USB_HID_KEYBOARD, SUPPORT_FIFO_QUEUES and also IN_COMPLETE_CALLBACK. This adds an additional delay generated by a hardware time between the release of each subsequent character from the queue to be sent to the host as key strokes and which can give higher resolution inter-key-stroke pauses than the endpoint's polling frequency steps. It also allows the delay to be modified during operation without requiring the USB connection to be re-emumerated.
For specific questions and feedback on this topic please use the following forum entry: USB Composite Devices and USB Keyboard test.
µTasker USB Device Configuration and Keyboard Testing. Copyright (c) 2004..2018 M.J.Butcher Consulting