Universal Serial Bus (USB) is now a common and vast framework for serial communication. The interface not only allows serial communication, but also functions as an electronic power source. Fortunately, popular AVR microcontrollers have USB interface capability and can be programmed to build USB devices. The USB specification is long and intimidating. It can be a difficult task to write a specific USB driver for a device.
Fortunately, Dean Camera has taken an initiative for the AVR community and built an open source USB framework for USB-enabled Atmel AVR8 and (some of) the AVR32 microcontrollers. The framework is called Lightweight USB Framework for AVRs (LUFA) and so far the fourth version of the framework has been published. The framework was released under the permissive MIT license. The open source library supports all Atmel USB AVRs and USB AVR boards.
The USB interface allows point-to-point communication. The device that controls USB data communication is called host and the other device that is operated is called slave or peripheral. The host controls data communication by sending requests to which the peripheral responds with descriptors. The first request the host sends for an attached peripheral event is for enumeration. During enumeration, the host's request for enumeration and peripheral device sends its own description, after which the host assigns an address and terminal number to the peripheral device. USB peripheral devices are categorized by classes. Following is the list of classes as per USB specification –:
1. Audio
2. CDC Communications and Control
3. Human Interface Device (HID)
4. Physical Device Class
5. Still images
6. Printer
7. Bulk Storage
8. Center
9. CDC Data
10. Smart Card
11. Content Security
12. Video
13. Personal health care
14. Audio/video devices
15. Outdoor device
16. USB Type-C Bridge Device
17. Diagnostic device
18. Wireless Controller
19. Miscellaneous Device
20. Application Specific Device
21. Vendor-specific device
USB classes are a means of defining devices based on their functionality so that the data format for different types of devices can be specifically defined. Each USB class has subclasses (device types that fork further) and follows specific USB specifications within the USB protocol. Just like the audio class device will follow the audio device class specification within the USB protocol. Check out the USB Implementers Forum website to learn about USB classes and the protocol specifications associated with them. The LUFA framework currently has drivers written for the following USB classes.
1. Human Interface Device (HID) Class
2. CDC Communications and Control
3. Printer
4. Bulk storage
5. Device firmware update (DFU) subclass of application-specific device class
Therefore, the framework can be used to create USB HID, CDC, printers, and mass storage peripherals or to implement host driver for the USB classes mentioned above. These are the most common peripherals used with personal computers. The framework also comes with a large number of demo projects, which include demo projects of USB HID devices like mouse, keyboard and joystick, demo projects of CDC class devices like audio input, audio output, Ethernet device and virtual serial, etc. the class-specific drivers written into the framework to implement device-specific functionality. Just like the keyboard demo project, it uses the HID Class driver to function as a generic HID keyboard. The framework is written according to the USB 2.0 specification and has host and device drivers for the USB device classes mentioned above. The drivers included in the framework support low-speed, full-speed, and high-speed USB modes.
At the USB protocol application layer, data communication is done through usage and data reports (input or output). The LUFA framework has high-level APIs, that is, functions that independently manage the sending of data reports or usage reports, as well as low-level APIs that implement the USB protocol for a USB class at the lowest implementation level of the specific protocol.
Now, it should be clear that
1. LUFA should be used to build USB peripheral devices on AVR microcontrollers.
2. LUFA can be used to manufacture specific USB peripherals for HID, CDC, mass storage, printers and applications.
3. LUFA includes generic drivers for both host and peripheral, so USB host drivers for the USB classes mentioned above can also be implemented using LUFA.
4. LUFA includes demonstration projects that illustrate the use of class-specific drivers to build specific USB peripherals or implement host-side USB driver.
Let's download the LUFA framework and start exploring the library files. When you unzip the library, it contains the following files and folders.
Fig. 1: Screenshot of the LUFA folder
Bootloader Folder – Any USB peripheral is controlled by the host, so the microcontroller in the peripheral must contain a bootloader to boot with the host. The Bootloader folder contains the bootloader files for USB HID, CDC, Mass Storage, Printer, and DFU class devices in separate folders.
Fig. 2: Screenshot of the Bootloader folder in LUFA
BuildTests folder – The folder contains the card driver templates and build test modules for the bootloader.
Fig. 3: Screenshot of the BuildTests folder in LUFA
Demos folder – The folder contains the demo projects that illustrate the use of class-specific drivers to build specific USB peripherals or implement the host driver.
Fig. 4: Screenshot of the Demos folder in LUFA
The folder contains three folders -:
Device – Demo projects for devices that function only as USB peripherals.
Dual role – Demonstration projects for devices that function as both peripherals and hosts.
Host – Demo projects that illustrate the implementation of device-specific host drivers.
There are demo projects using the library's USB class driver (inside the ClassDriver folder) and also low-level APIs (inside the LowLevel folder). The demo project within the ClassDriver folders accesses the library drivers specific to a USB class (such as HID, CDC, printer, etc.) through available APIs so that the device-specific low-level code is abstracted by the functions that manipulate the own data reports. Demo projects within the LowLevel folder access the library's drivers through functions that directly handle USB communication for the specific device class.
LUFA Folder – This folder contains the actual driver modules used to implement the USB protocol for different USB classes. The folder contains the template files, configuration files, and the deoxygen package.
Fig. 5: Screenshot of the LUFA folder
Driver modules are specifically in the Drivers folder. The folder contains the following folders.
Fig. 6: Screenshot of the Drivers folder in LUFA
The Board folder contains the board drivers for the AVR USB microcontrollers. The Misc folder contains miscellaneous drivers. The Peripheral folder has drivers for implementing AVR-specific code for ADC, SPI, TWI, Rs-232, and Serial SPI interfaces. The generic USB driver modules that actually implement the USB protocol in the LUFA framework are in the USB folder. The USB folder contains USB class specific driver modules (like HID, CDC, Printer, etc.) inside the Class folder and has low-level USB modules in the Core folder. It has a USB.h file that is imported into all demo projects and must be imported into any project built with LUFA. The USB.h header file further imports USB class specific driver modules (like HID, CDC, printer, etc.) with provision to import device-end or host-end driver module.
Platform folder – The platform folder contains the architecture-specific hardware platform drivers.
How to use LUFA
LUFA comes with a large number of demo projects. Demo projects are pre-configured to build and run correctly on the AT90USB1287 AVR microcontroller, mounted on the Atmel USBKEY board and running at an 8MHz master clock. Demo projects come in ClassDriver and LowLevel varieties.
It will be advisable to start with demo projects in the ClassDriver folder as they use pre-made USB class drivers to simplify the use of standard USB classes (such as HID, CDC, etc.) in user applications. In these demo projects, the project-specific module and header file can be modified or rewritten to implement a new project. Similarly, the Keyboard demo project in the LUFA-Source-FolderDemosDeviceClassDriverKeyboard folder contains Keyboard.c and Keyboard.h modules that can be modified to create a custom HID keyboard device. The modules in these demo projects use functions belonging to high-level APIs that directly deal with using or reporting data specific to the USB device class.
As in Keyboard.c, the CALLBACK_HID_Device_CreateHIDReport function handles data input reporting and the CALLBACK_HID_Device_ProcessHIDReport function handles data output reporting. Data and usage reporting are application layer features of the USB protocol.
If using another microcontroller other than AT90USB1287, the Makefile in the same folder must be modified to configure the code for the specific AVR controller and its clock speed. Only AVR controllers whose card drivers are written and included in the framework can be used.
For absolute control over specific USB class implementation (such as HID, CDC, printer, etc.), low-level demo projects can be modified. In low-level demo projects, the required USB class is implemented directly using lower-level APIs. To modify these designs, you will need a strong understanding of the USB protocol and its implementation for the specific USB class (such as HID, CDC, etc.). If work on these demonstration projects requires the embedded engineer to brainstorm USB class specifications, it won't be a surprise. Therefore, as you progress through these demonstration projects, you will discover how a specific device or host driver for a USB class is actually implemented.
Furthermore, the framework is open source and an embedded engineer can struggle to write a board driver (not available in the framework at this time) or write driver code (host and device) for additional USB class.