Board Ports

LUFA (Formerly MyUSB) Library, Projects 1 Comment »

MyUSB is now being ported to compile across the range of Atmel development/demonstration boards - the USBKEY, STK525 and STK526. This is in addition to the ports to the AT90USB162 and AT90USB82 AVR ports done earlier.

Unfortunately, this has resulted in a few directory changes — the “AT90USB_64x_128x” has been renamed to “AT90USBXXX”, and the “USBKEY” directory is now “Board”. By selecting the board to be compiled for (when using the board-level drivers) in the user application’s makefile, the need to change the application source code for each board is eliminated. This is the best solution, and the least intrusive.

Interrupt-driven devices

LUFA (Formerly MyUSB) Library, Projects No Comments »

While my laptop’s off at the doctors getting an operation to save its life, my hands are tied development-wise. So while I can’t work on MyUSB, I thought I’d at least answer a reasonably common question about MyUSB.

To retain some familiarity to those coming from Atmel’s honking-great big USB library, MyUSB is built using a very similar structure (but no code was re-used, no plagiarism accusations please). This means that when in device mode, the control requests made by the host to endpoint 0 of the device are polled, rather than interrupt driven. I made this choice for two reasons: one being to remain compatible with the behavior of Atmel’s library, and two because it is likely that having the lengthy processing interrupt driven will more than likely be detrimental to the end user, unless they are aware of it and specifically code around it.

However, that does not mean that MyUSB cannot be used in interrupt driven device (only, for now) mode. By the use of the following method, it should be possible to change over the library to interrupt driven control requests, with no changes to the library itself:

1) Don’t call the USB_USBTask task

2) Hook the USB_Reset event in your code. Inside the event, add the code:

UEIENX |= (1 << RXSTPE);

which will enable the control received interrupt for the control endpoint.

3) Add the endpoint interrupt handler to your program:

ISR(ENDPOINT_PIPE_vect)
{
   if (Endpoint_HasEndpointInterrupted(
    ENDPOINT_CONTROLEP))
   {
      Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);

      if (UEINTX & (1 << RXSTPI))
         USB_Device_ProcessControlPacket();

      UEINTX = 0;
   }

 

   // Other endpoint interrupt code here

}

 

 

Those three steps combined should change the interrupt processing over to fully interrupt driven. Other endpoints can also be interrupt driven (and processed in the same ISR) — see the documentation and example projects.

The Mass Storage Layers

General No Comments »

Plenty of people have been asking around on AVRFreaks for information on making a device which is capable of showing up as a removable storage device under Explorer, so that images or logs can be downloaded with any modern operating system. What these people do not know is that the creation of a device is quite a complex task, involving several “layers” which must be correctly implemented before it will work correctly.

I’m taking a break from my usual boring blogs to try to make the inner workings of such a device a little less of a mystery.

First, let’s look at the six different layers required for a typical mass storage device:

Layers of communication for a Mass Storage Device

The MyUSB Mass Storage Device demo only implements layers 1 through 4. This is because the demo is for a “dumb” storage device, in that all it does is expose a readable/writable storage medium for the host OS. The host’s OS is free to use whatever storage scheme it sees fit to format the device, which is why the demo disk can be formatted to any scheme desired by the user. The device itself never tries to create files on the disk, so the last two layers are unnecessary.

Now, let’s look at the different layers in a little more detail.

LAYER 1 - PHYSICAL LAYER:

The physical layer is the lowest level layer of USB, and is the protocol dictating the exchange of data between a USB host, and one or more devices present on the USB bus. It provides a means of detecting when devices are added or removed, and for data transmission to an addressed device. The AT90USB series AVR microcontrollers include a full USB controller, which takes care of the entire layer 1 for us, allowing us to interact on the physical layer via a group of exposed USB control and status registers.

The physical layer is generally not of any concern to embedded developers, unless of course it is being bit-banged or otherwise generated (as is the case with the software-only USB implementations for some AVR models available on the web) without the aid of a dedicated USB controller.

LAYER 2 - CONTROL LAYER:

Layer 2 is the layer which handles all the device-level requests. This layer controls the creation and modification of the endpoints in a device, the processing of device control commands - including class-specific control commands - and the fetching of the device’s “descriptors” (structures containing information for the host about the device’s capabilities, features, implemented classes and power requirements) for the host

MyUSB handles the control layer transparently, only handing of the processing of such requests if they are class-specific commands rather than general device commands. In the case of the Mass Storage class, there are special control commands for the resetting of the storage device, and for the retrieval of the number of LUNs (Logical UNits, logical disks in the device).

LAYER 3 - CLASS LAYER:

This layer is specific to each implemented class. The USB specification provides the general USB communication specification, and is completely function-agnostic. Each device may implement one or more of the standard “classes” defined by the USB organization. In the case of these defined classes, the method of data transfer inside the class is also defined.

For the Mass Storage class, there are two schemes for data transfer - CBI (designed for floppy drives) and the Bulk-Only transport specification. The Bulk-Only transport is the one that is the most used, and specifies how commands and data to/from the host should be wrapped up in a well-defined manner to provide error tolerance.

LAYER 4 - SCSI Layer:

Up until now, all the layers have been completely USB-specific. However, the Mass Storage class calls for the actual medium commands (for reading, writing, status checking and the like) to be standard SCSI commands. This means that the USB transport is really just one giant wrapper for a SCSI drive - something made obvious on Linux platforms, where the kernel messages indicate a virtual SCSI driver being initiated when a USB Mass Storage device is inserted.

Once commands have been removed from the Bulk-Only wrapper, they are passed through the SCSI decoder. The SCSI layer then performs the required actions on the physical medium, resulting in data being read or written from the disk.

LAYER 5 - STORAGE LAYER:

Layers 5 and 6 are optional, and are only required if the USB device wishes to manipulate the data on the disk so that the host can read it (typical for data loggers, digital cameras and the like). This layer is able to decode the file system of the disk, so that files and folders can be added, deleted, renamed or otherwise manipulated. Because embedded devices contain limited resources, typically only one file system is supported, forcing the host to use the same file system to prevent corruption. For this reason, Mass Storage MP3 players, cameras and other devices are typically locked into using the easy to program and for and royalty free FAT file system.

LAYER 6 - FILE FORMAT:

Layer 6 is the easy one, and just entails being able to write data to the file system in the file format of choice. Loggers normally save in simple ASCII files, which require no file structure, although more complicated devices such as digital cameras need to be able to write to an image format such as JPEG.

And there you have it - a basic overview of the different layers required for a USB Mass Storage device. Hopefully this will be of some interest to embedded engineers interested in learning the USB specification.

Model Port

LUFA (Formerly MyUSB) Library, Projects No Comments »

Still no progress on the bootloader front - read is fine, write still doesn’t work. I’ve been unable to get a hold of anyone at Atmel to bail me out (by explaining what exactly FLIP is expecting) so I’m going to have to continue my educated trial-and-error.

On a positive note, I’ve ported the library to the other current memebers of the AT90USB family, the AT90USB162 and AT90USB82. The changes are yet to be tested, but should allow MyUSB to be compiled across the entire USB AVR range.

Semi-literate

General, LUFA (Formerly MyUSB) Library, Projects, University No Comments »

Birthday’s are neat. While I’m not much of a consumer - at all - birthday’s do allow one to indulge slightly and make living just a little more pleasant. In the case of this birthday, I’m now a proud owner of a few more Stargate seasons, a new Maxtor Onetouch Mini 4 external hard disk for backups and a new Logitech VX Revolution wireless mouse.

Paying a little more gives a lot more benefit, I’ve come to learn. Cheap is cheap, in both quality and service. Now I’ve got a good quality Toshiba notebook and Logitech headphones and mouse, I’ve realized just how much nicer the spit-and-polish is on the name-brand products. No more Chinese cheapies for me!

One gripe so far; the Maxtor Onetouch backup software doesn’t work for me. The software detects the presence of my drive fine, but is hell-bent on indicating it as drive C:\ instead of its real drive letter allocation. Not a huge problem if I could manually set it, but as it is I can currently only backup C:\ to itself. Not a very useful proposition but one I hope to rectify with technical support.

As for the bootloader, I can now read back data correctly. Writing is still an issue which I have to tackle, but at least it’s the only remaining issue. I got back to University for year 2 in a week and a half, so I hope to have it finished completely well before then.

Old and wrinkly

General, LUFA (Formerly MyUSB) Library, Projects No Comments »

I thought I was being prematurely aged by my inability to get my bootloader working (not through lack of effort by any means) - turns out I’m just getting old. As of one minute ago, I’m now officially 19 years old.

Still working on getting the flash read and flash/EEPROM write commands working. I’m concentrating purely on the flash read for the moment, but it’s causing me a great deal of stress. As far as I can tell, my code’s perfect - so why I’m getting corrupted data after the first 1KB or so is beyond me. Perhaps Atmel support will be able to suggest something, but I’m not hopeful. Anyone out there want to pitch in?

Retraction

General, LUFA (Formerly MyUSB) Library, Projects No Comments »

Now that I’m more well-rested, I see that the bug I posted about in my previous entry wasn’t a bug at all - I just missed a relevant part of the datasheet (for those wondering, before you can disable the watchdog, you must clear the watchdog reset source indicator flag in MCUCSR).

The bootloader’s progressing a bit, but I’m a bit stuck trying to figure out the memory upload command. As far as I can see the algorithm’s fine, but the data being uploaded is corrupt. I’m either going to have to ask Atmel about it, or check out the host-side source of an open source DFU project.

Scary to think that I’ll be 19 in only 2 days. However, being born on Valentine’s day does have its advantages…

Static Advancement

LUFA (Formerly MyUSB) Library, Projects No Comments »

*** It’s very late and I’m dead tired, so please excuse the following rambling mess in advance. ***

I do like a set of small, well defined specifications. A huge spec such as SCSI, USB, etc is damn hard to read and understand all at once, and can leave you feeling overwhelmed and confused — especially on what parts exactly you need to implement. The USB DFU Class and Atmel’s DFU Bootloader Datasheet are both small, concise and actually fun to implement.

After a bit of head scratching and investigation, I’ve found a bug in the current avr-lib-c library, in the watchdog reset routine wdt_reset() of <avr/wdt.h>. The problem is that it fails silently on the AT90USB1287, because of the choice of instructions. The AVR architecture gives three ways to access the contents of registers — short IO space, longer extended IO space, and slow RAM-mapped access. The wdt_disable() routine uses the assembly instructions IN and OUT (for extended IO mapped space) to access one of the watchdog configuration registers which, due to the number of features in the AT90USB1287 requiring registers (and thus addresses), resides in the memory mapped space only.

My fix is currently a small custom routine to disable the watchdog in the bootloader only. All the other demos use the avr-lib-c routine, which should be patched soon by one of the developers. The DFU bootloader can jump to the application space using both the watchdog and an actual jump, so adding the custom routine to all the demos isn’t needed.

I’ve also enhanced the USB portion of the MyUSB library a bit, by adding the ability to statically specify USB options (normally passed in dynamically by the Options parameter of the USB_Init() routine) via the makefile. This results in a decent flash space savings, with the downside that the options cannot be altered while the program is running - a feature not needed on most apps. The USB_Init() routine’s parameters now also alter depending on the compile time options — specifying USB_DEVICE_ONLY or USB_HOST_ONLY removes the “Mode” parameter, and specifying the new USE_STATIC_OPTIONS parameter removes the “Options” parameter.

My Boot

LUFA (Formerly MyUSB) Library, Projects No Comments »

The MyUSB Bootloader is coming along nicely. It resides properly in the boot space of the USB1287, and is recognised by the FLIP software correctly. I’ve still got the meat of the commands (erase/program flash and EEPROM) to go, but the already implemented commands (jump to app, read signature, erase app) work well, as does the rest of the bootloader.

The USB component of the MyUSB library expects the descriptors of a USB device to be located in the flash (PROGMEM) space. Locating the bootloader to the boot section highlighted this as a problem, as the pgm_* macros don’t work across the 64KB flash boundary. As a result, I’ve added in a new compile-time macro which tells the library to use descriptors stored in RAM. It’s not a bad compromise - I think it far more likely to be used elsewhere in user apps than macros to enable the library to work with PROGMEM descriptors in the boot section.

Feedback

LUFA (Formerly MyUSB) Library, Projects No Comments »

Thanks to all those who have given feedback on the current and past MyUSB releases. I appreciate it all - suggestions, bug reports, or even just a friendly email about how you’re using the library.

I’m currently working simultaneously on two new additions to the library; a new DFU class bootloader compatible with Atmel’s FLIP application, and a new Still Image Host demo for connection to compatible cameras.

After the completion of the two sub-projects, I might create a second bootloader, using the CDC protocol. This would enable the device to enumerate as a virtual serial port and thus work with the myriad of bootloader software out there, such as Steve’s BLIPS project.

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in