LUFA – First Steps Part 2

Device Descriptors

Now that the overall project configuration has been configured we need to supply information about the device itself. Descriptors are data structures a USB device passes to the host computer during initialisation and are the key to ‘plug and play’ operation. An excellent introduction to the various kinds of descriptor can be found here.

The monitor project is in essence a Serial to USB converter so I decided to copy the descriptors from the Serial to USB example project. The relevant files are Descriptors.h and Descriptors.c. I copied these into my project root. You also need to ‘Add’ them to the project using the Solution Explorer window.

The Descriptors.h file needs to be edited and the function prototype for CALLBACK_USB_GetDescriptor deleted. The version below has been edited to remove comments for clarity:
LUFA Library
Copyright (C) Dean Camera, 2014.

dean [at] fourwalledcubicle [dot] com


#include <avr/pgmspace.h>
#include <LUFA/Drivers/USB/USB.h>

#define CDC_TXRX_EPSIZE 32

typedef struct
USB_Descriptor_Configuration_Header_t Config;

// CDC Command Interface
USB_Descriptor_Interface_t CDC_CCI_Interface;
USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;

// CDC Data Interface
USB_Descriptor_Interface_t CDC_DCI_Interface;
USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
} USB_Descriptor_Configuration_t;

enum InterfaceDescriptors_t
INTERFACE_ID_CDC_CCI = 0, /**< CDC CCI interface descriptor ID */
INTERFACE_ID_CDC_DCI = 1, /**< CDC DCI interface descriptor ID */

enum StringDescriptors_t
STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
STRING_ID_Product = 2, /**< Product string ID */


Posted in AVR, Microcontroller, USB | 5 Comments

LUFA – First Steps Part 1


This week I used the LUFA framework to implement a simple USB-Serial device. USB isn’t at the trivial end of the embedded system development spectrum and LUFA goes a long way to ease the pain but getting started can be difficult. Here goes the first blog post…

The starting point for my little project was a need to debug the message exchange between nodes in an XpressNet bus. XpressNet is a model railway control bus developed by Lenz Elektronik GMBH. It uses RS-485 level signals with 9-bit characters over an asynchronous serial line. One node, the controller, operates as the bus master. All other nodes operate as bus slaves and wait until polled before becoming active on the bus.

To monitor the bus the RS-485 level signal is routed through a level converter, a TI 75176, and then into an AVR ATMEGA32U4 microcontroller. The microcontroller attaches to the monitoring computer using USB. This article focuses on using the open source LUFA framework to bring XpressNet messages into the PC over a USB serial channel.

LUFA Sample Code

LUFA is an acronym for Lightweight USB Framework for AVRs and was written by Dean Camera. You install it into Atmel Studio, the Atmel IDE, using the Studio Extension Manager. Once installed the LUFA extensions become available through the ASF wizard. I’m no ASF expert but it appears to function as a large cut and paste database.

A good way to get started with LUFA is to create the USB to Serial example and read through the code. Start with File->New->Example Project…, expand the item “Four Walled Cubicle…” and select “USB to Serial Converter – AVR8 Architecture”. This creates a new project structure and copies all the required LUFA files into the selected directory. A quick note, Atmel Studio doesn’t like directory names with embedded spaces.

At this point it is possible to compile the sample code and download it to a suitable AVR device, in my case an ATMEGA32U4 breakout from Sparkfun. Am happy to report that it worked first time. Whilst I recommend reading the sample code it can be a little daunting, there is a lot of code and it can be difficult to know where to start.

The Monitor Project

I could have started with the Serial Converter example and changed it to fit my needs. However, this doesn’t really answer the question of how to add LUFA support. More importantly it doesn’t tell me what I need to do to get LUFA working with the minimal amount of code.

So step one was to create a new project using the New Project tool. In my case a C language executable targeting the ATMEGA32U4. Once created I then applied the ASF Wizard to add LUFA support. This can be a little tricky, the ASF Wizard will complain about a missing board. I found that by either cancelling the board dialog or accepting a board of ‘None’ would allow me to progress. You then need to select the FourWalledCubicle extension and then ‘Add’ the ‘LUFA USB Driver (driver)’ module. Clicking the ‘Apply’ button copies the relevant LUFA code to your project. You should have your main C source file in the project root plus the LUFA directory ‘src’. Clicking the ‘Build Solution’ button should result in compilation failure due to some undefined symbols (F_CPU and F_USB).

The LUFA documentation discusses a build system based on Make. I found I could configure the project using the standard Studio settings without resorting to a custom makefile and wonder whether Dean has done a better job of Studio integration that his documentation leads you to believe.

I got the project to compile successfully by defining the following symbols under the project properties (Toolchain->AVR/GNU C Compiler->Symbols):

  1. DEBUG
  3. F_CPU=16000000
  4. F_USB=16000000

From memory, items 1 & 2 were created by the ASF Wizard. The effect of USE_LUFA_CONFIG_HEADER is discussed in the next section. Items 3 & 4 must be added. The value here is the clock frequency in Hertz; the Sparkfun board comes fitted with a 16MHz crystal. The ARCH symbol isn’t strictly necessary, I found it defaults to ARCH_AVR8 somewhere in the LUFA framework. I prefer to specify these type of things upfront as it makes things a little easier to understand.

At this point the project should build cleanly.

LUFA Configuration

The monitoring project is designed to operate as a USB device, over a fullspeed, i.e. 12Mb/s, connection. It logs a serial data stream so I decided to implement it as a communications device. The USB terminology is Communications Device Class or CDC device for short.

LUFA itself is designed to support multiple Atmel micro controller families and USB modes. Defining the symbol USE_LUFA_CONFIG_HEADER forces the LUFA framework to take its global settings from the configuration file src/Config/LUFAConfig.h. The sample below is abbreviated, anything not mentioned is to be assumed irrelevant and has been commented out the source file. Further information is found in the LUFA documentation under “Developing with LUFA/Summary of Compile Tokens”.

LUFA Library
Copyright (C) Dean Camera, 2014.

dean [at] fourwalledcubicle [dot] com

/** \file
* \brief LUFA Library Configuration Header File (Template)
* This is a header file which can be used to configure LUFA's
* compile time options, as an alternative to the compile time
* constants supplied through a makefile. To use this configuration
* header, copy this into your project's root directory and supply
* the \c USE_LUFA_CONFIG_HEADER token to the compiler so that it is
* defined in all compiled source files.
* For information on what each token does, refer to the LUFA
* manual section "Summary of Compile Tokens".

#ifndef __LUFA_CONFIG_H__
#define __LUFA_CONFIG_H__

#if (ARCH == ARCH_AVR8)



#elif (ARCH == ARCH_XMEGA)
... SNIP ...

#error Unsupported architecture for this LUFA configuration file.


LUFA Options

Setting Description

Hardcodes the USB_Init function parameter.

Allows USB Fullspeed operation
Enables the on-chip 3.3V regulator
Lets the LUFA code figure out the PLL setting automagically
USB_DEVICE_ONLY LUFA supports USB hosts and devices. The monitor operates as a USB device, only include that part of the framework.
USE_FLASH_DESCRIPTORS Device descriptors are data structures used to control USB operation. See Part 2 for descriptor discussion. Placing the descriptors in program Flash makes them read-only but saves on RAM.
FIXED_CONTROL_ENDPOINT_SIZE Controls the buffer size allocated to the control endpoint (Endpoint 0)
DEVICE_STATE_AS_GPIOR Some AVR microcontrollers provide user controlled registers in their IO map. Selects GPIO register 0 to hold the USB state
FIXED_NUM_CONFIGURATIONS Only one USB configuration exists
INTERRUPT_CONTROL_ENDPOINT Allows the function USB_USBTask() call to be managed be the LUFA framework. User does not need to call

Continue with Part 2…

Posted in AVR, Microcontroller, USB | Leave a comment