Universal Serial Bus (USB) is now a common and vast framework for serial communication. The interface not only allows serial communication, it also works as electronic power supply. The popular AVR microcontrollers fortunately have the USB interface feature and can be programmed to build USB devices. The USB specification is long and intimidating. It can be a daunting task to write a device specific USB driver.
Fortunately, Dean Camera took 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 named Lightweight USB Framework for AVRs (LUFA) and till now fourth version of the framework has been published. The framework has been released under the permissive MIT License. The open-source library supports all the Atmel USB AVRs and USB AVR boards.
The USB interface allows peer to peer communication. The device that controls the USB data communication is called host and the other device that gets operated is called the slave or peripheral. The host controls the data communication by sending requests to which the peripheral responds with descriptors. The very first request that the host sends to a peripheral on attach event is for enumeration. During enumeration, the host request for enumeration and peripheral device sends its own description after which host assigns an address and endpoint number to the peripheral device. The USB peripheral devices are categorized by classes. The following is the list of classes according to the USB specification – :
2. Communications and CDC control
3. Human Interface Device (HID)
4. Physical Device Class
5. Still Imaging
7. Mass Storage
10. Smart Card
11. Content Security
13. Personal Healthcare
14. Audio/Video Devices
15. Billboard Device
16. USB -Type C Bridge Device
17. Diagnostic Device
18. Wireless Controller
19. Miscellaneous Device
20. Application Specific Device
21. Vendor Specific Device
The USB Classes are means of defining devices on the basis of their functionality so that the data format for the different device types could be defined specifically. Each USB Class has sub-classes (further bifurcating device types) and follows specific USB specifications within the USB protocol. Like the Audio Class device will follow 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. Communications and CDC control
4. Mass Storage
5. Device Firmware Upgrade (DFU) Subclass of Application Specific Device Class
Therefore, the framework can be used for making HID, CDC, Printer and Mass storage USB peripherals or to implement host driver for the above mentioned USB classes. These are the most common peripherals that are used with the personal computers. The framework also comes with large number of demo projects which includes demo projects of USB HID devices like mouse, keyboard and joystick, demo projects of CDC class devices like Audio In, Audio Out, Ethernet device and Virtual Serial device etc. These demo projects utilizes the class specific drivers written in the framework for implementing the specific device functionality. Like the demo project for keyboard uses HID Class driver to function as a generic HID keyboard. The framework has been written according to the USB specification 2.0 and has both host and device drivers for the above mentioned USB device classes. The drivers included in the framework support the Low Speed, Full Speed and High Speed USB modes.
At application layer of the USB protocol, the data communication is done through usage and data (input or output) reports. The LUFA framework has the High Level APIs i.e. functions that independently handle sending the data reports or usage report themselves 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 for building the USB peripheral devices on AVR microcontrollers.
2. LUFA can be used for making HID, CDC, Mass storage, Printer and Application specific USB peripherals.
3. LUFA includes generic drivers for both host and the peripheral so host USB drivers for the above mentioned USB classes can also be implemented using LUFA.
4. LUFA includes demo projects illustrating the use of class specific drivers for building specific USB peripherals or implementing host side USB driver.
Lets download the LUFA framework and start exploring the library files. On unzipping the library, it has the following files and folders.
Bootloader folder – Any USB peripheral is controlled by the host, therefore, the microcontroller on the peripheral should contain a bootloader to initialize itself with the host. The Bootloader folder contains the bootloader files for the HID, CDC, Mass storage, Printer and DFU USB class devices in separate folders.
BuildTests Folder – The folder contains the board driver templates and the build test modules for the bootloader.
Demos Folder – The folder contains the demo projects illustrating the use of class specific drivers for building specific USB peripherals or implementing the host driver.
The folder contains three folders -:
Device – Demo projects for devices that work as USB peripheral device only.
DualRole – Demo projects for devices that work as both peripheral and host.
Host – Demo projects illustrating implementation of device specific host drivers.
There are demo projects using library USB class driver (inside ClassDriver folder) as well low level APIs (inside LowLevel folder). The demo project inside ClassDriver folders access the library drivers specific to an USB Class (Like HID, CDC, Printer etc) through available APIs so the low level code specific to the device is abstracted by functions handling the data reports themselves. The demo projects inside LowLevel folder access the library drivers through functions that directly handle the USB communication for the specific device class.
LUFA Folder – This folder contains the actual driver modules that are used for implementing the USB protocol for different USB classes. The folder contains the template files, configuration files and the deoxygen package.
The driver modules are specifically in the Drivers folder. The folder has following folders within it.
The Board folder contains the board drivers for the USB AVR microcontrollers. The Misc folder has the miscellaneous drivers. The Peripheral folder has drivers for implementing AVR specific codes for ADC, SPI, TWI, Rs-232 and Serial SPI interfaces. The generic USB driver modules which actually implement the USB protocol in the LUFA framework are in the USB folder. The USB folder contains the USB Class (like HID, CDC, Printer etc) specific driver modules within the Class folder and has low level USB modules in the Core folder. It has a USB.h file which is imported in all the demo projects and should be imported in any project built using LUFA. The USB.h header file further imports USB Class (like HID, CDC, Printer etc) specific driver modules 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
The LUFA comes with large number of demo projects. The 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. The demo projects come in ClassDriver and LowLevel varieties.
It will be wise to start with demo projects in ClassDriver folder as they use the pre-made USB Class Drivers to simplify the use of the standard USB classes (Like 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. Like, the demo project for keyboard in the LUFA-Source-FolderDemosDeviceClassDriverKeyboard folder contains Keyboard.c and Keyboard.h modules which can be modified to make a custom HID keyboard device. The modules in these demo projects use functions belonging to high level APIs which directly handle the usage or data reports specific to the USB device class.
Like in the Keyboard.c, CALLBACK_HID_Device_CreateHIDReport() function handles the data input report and CALLBACK_HID_Device_ProcessHIDReport() function handles the data output report. The data and usage reports are features of application layer of the USB protocol.
If using other microcontroller than AT90USB1287, the Makefile in the same folder should be modified to configure code for the specific AVR controller and its clock speed. Only AVR controllers whose board drivers are written and included in the framework can be used.
For absolute control over the specific USB Class (like HID, CDC, Printer etc) implementation, Low level demo projects can be modified. In Low level demo projects, the required USB class is implemented directly using lowest level APIs. For modifying these projects, a strong understanding of the USB protocol and its implementation for the specific USB Class (like HID, CDC etc) will be necessary. If working on these demo projects require the embedded engineer to brainstorm through the USB Class specifications, it will not be a surprise. So on advancing through these demo projects, how actually a device or host driver specific to a USB class is implemented will be discovered.
Moreover, the framework is open-source and an embedded engineer can endeavour to write a board driver (not available in the framework at present) or write driver code (host and the device) for additional USB Class.
Filed Under: Articles