Thanks to the folks at Newark/Farnell, I have been given the opportunity to review another microcontroller development board. This time, it’s the Atmel AT90USBKEY, a cool little USB development board. The AT90USBKEY is powered by the Atmel AT90USB1287 microcontroller. Here are some pictures of the unboxing:
It comes with several cool goodies:
- The development board itself (which has a USB mini-AB receptacle)
- A standard USB A-to-mini-B cable that you can use to connect the board to your computer
- A special USB cable — on one end, it has a USB A receptacle, and on the other end it has a USB mini-A connector
- I’ve never seen anything like this cable before. The mini-A end of it plugs into the development board, and then you can plug whatever device you want into the “A” receptacle, allowing the board to act as a USB host rather than a device.
- A 9V battery clip for powering the microcontroller if you’re using it in host mode with the aforementioned cable
Since this board uses some weird (but standard) USB connectors, I’d like to explain them in detail right now before I finish reviewing the product.
USB connectors:
As you probably know, there are normally two major types of USB connectors: A and B. You usually plug a device with a B receptacle into a host with an A receptacle (or a hub with A receptacles). This is why most USB cables you find have an A connector on one side and a B connector on the other side. An A-to-A cable doesn’t make much sense (although I have seen them!), and neither does a B-to-B cable.
You also commonly see devices that have smaller USB receptacles, such as digital cameras and microcontroller development boards. They tend to use mini-B or micro-B receptacles. Because of this, another type of cable is very common: A-to-mini-B and A-to-micro-B. I have tons of these types of cables laying around.
One type of connector you don’t see very often is mini-A or micro-A. They do exist, but they aren’t very common because most computers and hubs have full-size A receptacles. There is a major reason you’d find them, though. Read on…
What about a USB port that is supposed to be either a device or a host, depending on what you connect it to? Should it have an A receptacle or a B receptacle? The answer is “neither.” This is why mini-AB and micro-AB receptacles exist, and it’s called USB On-The-Go. They can accept either an A connector or a B connector (of the required size — mini or micro). Depending on what type of cable you plug in, it will decide whether it should act as a host or a device. In practice, I haven’t seen this type of receptacle on consumer devices, but I see it a lot with development toolkits.
This is the type of receptacle that is on the AT90USBKEY. If you use an A-to-mini-B cable to plug it into your computer, it knows it should act as a device and does so. On the other hand, if you use the other supplied cable that is mini-A-to-A, it knows it should act in host mode, it will behave like one. The USB controller will give you, the programmer, the ability to detect whether it’s currently a host or a device. The A receptacle on the other end of the mini-A-to-A cable just makes it convenient to plug in a standard USB device because you don’t find many USB devices that have a mini-A connector.
I honestly can’t think of any reason for why you would need a mini-A or micro-A connector other than for a USB On-The-Go device, at least as of the time of this writing. Anyway, that is my quick introduction to the AT90USBKEY’s USB port. Enough about that — let’s get on with the review!
The review:
AVRs are very interesting microcontrollers for a number of reasons.
- First of all, they are well-supported in the hobbyist community. The Arduino project is a good example of this. There are plenty of people making cool hobby projects with AVRs (myself included–more on this in a later post!). There is an excellent set of community-supported development tools for the AVR platform — binutils, gcc, avr-libc, and avrdude are a few of the essentials.
- They are 8-bit microcontrollers (well, except for some of the newer AVRs). In the 32- and 64-bit world of PCs, it can be kind of strange going back to an 8-bit system. Although C compilers will automatically generate 8-bit code that manipulates larger variables (16- and 32-bit integers, for example), you have to be careful about performance and interrupt safety when working with bigger variables.
- It gets better — not only are these microcontrollers 8-bit, but they are weird because they have different address spaces for RAM and program instructions (stored in flash), as opposed to something like an ARM microcontroller where everything shares different chunks of the same address space. This requires some weird coding if you’re trying to access constant variables stored in the flash memory, and also prevents you from executing instructions stored in RAM. (Side note: This distinction is sometimes called Harvard architecture versus von Neumann architecture, although modern processors seem to use aspects of both architectures in their designs.)
- They tend to be very straightforward to program. The built-in peripherals are pretty easy to understand in my experience, and the datasheets that explain the peripherals are pretty easy to read. Recall when I covered the AVR’s SPI peripheral in a previous post–not too bad, right?
Like I said earlier, this board uses the AT90USB1287 microcontroller, which is an 8-bit AVR. You may notice the “USB” in the name. The reason for that is that because you can’t just pick any AVR to be a USB device. This is a chip with all of the necessary hardware built-in to be either a USB host or device, so the name lets you know that. More about this chip: it has 128 kilobytes of flash, 8 kilobytes of RAM, 4 kilobytes of EEPROM, and it can run at a maximum of 16 MHz, although this board only has an 8 MHz crystal on it.
When I said it has 128 kilobytes of flash and 4 kilobytes of EEPROM, you may have been wondering what I meant. What’s the difference? In 8-bit AVRs, flash is designed for code storage and must be erased in large chunks. If you want to erase a byte to write a new value in its place in flash, you must erase many of the neighboring bytes as well. For that reason, it’s not ideal for storing individual byte values that you will have to change in your program. On the other hand, EEPROM is meant for storing data and can be erased on a byte-by-byte basis. The idea is to put your code and large constants into flash because they will only change when you change the firmware. You can put program configuration values that must be saved across power cycles into the EEPROM and not worry about erasing other nearby bytes when you change them.
Aside from the microcontroller, the board also has a small joystick, a temperature sensor, two LEDs (which can each be green or red), two buttons (one is for resetting, the other one is a bootloader entry button which can also be used for your own purposes), and two external memory chips. It comes programmed with a demo application that acts as a mouse and USB disk when plugged into your computer. The demos seem to work great. It also comes from the factory with a USB bootloader, so you don’t even need any extra hardware to program it. The bootloader puts the device into a USB DFU (device firmware upgrade) mode if you’re holding down the bootloader button when it powers on. In order to flash your own program to the board through the bootloader, you will need to use a program compatible with the DFU bootloader — Atmel’s FLIP and the dfu-programmer open-source project are two ways to get it done. I’ll write more about them later in this review. If you want to use JTAG to program it instead, a 10-pin JTAG header came soldered on mine too. For that, you would need a JTAG-compatible programmer such as the AVR Dragon or the AVR ONE!.
Just like I said in my last microcontroller development board review, the demo apps are exciting and all, but the real value in these boards comes when you write your own programs. This can be quite complicated in this case because the most impressive built-in peripheral is the USB controller. USB is a monster of an interface to use for a simple program. Remember when I said earlier that AVRs are straightforward to program? Well, the USB controller is an exception. It’s not Atmel’s fault — it’s just that USB is complicated. Luckily, Dean Camera has come out with a really exciting project called LUFA. It handles talking to the USB controller for you, so all you have to do is work with a higher-level API instead of talking directly with the USB registers in the microcontroller. I’m not going to cover LUFA in this review, but you should definitely check it out.
For the rest of this review, I’m going to walk through getting a development environment set up for programming to this board, and then I will make a simple demo app (although it won’t involve the USB controller — sorry!). We will, however, use the USB capability of the chip to flash your new compiled program using the bootloader. Here goes nothing!
Setting up the development environment:
I really enjoy using Eclipse for my programming, so I’m going to create an Eclipse-based environment. Let’s start out by downloading Eclipse. As of the date of this review, the latest version of Eclipse is Indigo (3.7.1). Download the Eclipse C/C++ environment for your operating system from this page. Extract the contents of the zip archive to a location of your choice. (I’ve found that some versions of Windows don’t like the zip file very well — if you run into any problems, use 7-zip to extract the file instead of the built-in Windows extraction tools).
Open up Eclipse and install the AVR Eclipse plugin using the directions provided on this site. This will make it easy to create cross-compiled AVR projects in Eclipse. (Otherwise, you’d have to mess around with a bunch of C compiler settings to tell Eclipse to use AVR gcc instead of your system’s default gcc)
Now, install the AVR development tools. This will differ based on which operating system you’re using:
If you’re using Windows:
Install the Windows AVR development tools. This will include gcc, binutils, avr-libc, and avrdude. They are packaged together and called WinAVR (note: when accessing this site, I occasionally get redirected to another site because of the webring they are using — if that happens, just click the back button in your browser). Go ahead and download the latest version of WinAVR and install it. Make sure during the installation you check any boxes asking to add WinAVR binaries to your path.
While you’re at it, install Atmel’s FLIP. We will use this to program the new device.
You will probably have to quit and relaunch Eclipse at this point so that it gets the changes that WinAVR made to the system PATH variable. If you don’t relaunch it, it probably won’t be able to find the AVR compiler because it’s still using the old PATH variable.
If you’re using Linux:
Install your distribution’s AVR development tools. In Ubuntu, you can type the command:
sudo apt-get install binutils-avr gcc-avr avr-libc avrdude dfu-programmer
(You don’t really need avrdude right now, but it’s good to have in case you ever start using JTAG or ISP to program AVR devices)
There’s a little more to it, though. Linux can be picky about the permissions of USB devices, so you will probably need to add a udev rule. If you don’t add this udev rule, you will have to run dfu-programmer as root, which is less than ideal. Create the file /etc/udev/rules.d/99-dfu-programmer.rules containing:
SUBSYSTEM=="usb", ACTION=="add", SYSFS{idVendor}=="03eb", SYSFS{idProduct}=="2ffb", MODE="660", GROUP="plugdev", SYMLINK+="at90usb-%k" BUS=="usb", ACTION=="add", SYSFS{idVendor}=="03eb", SYSFS{idProduct}=="2ffb", MODE="660", GROUP="plugdev"
Once you’ve created the file, type:
sudo udevadm control --reload-rules
The purpose of this last command is to get udev to reread its list of rules. After doing this, the permissions for the USB device should be correct the next time you plug it in. By the way, I got these udev instructions from the AVR Freaks wiki, but their wiki is so slow and messed up right now that I’m not going to bother linking to it.
If you’re using Mac OS X:
Sorry, I’m lazy, but it shouldn’t be too bad. You just need dfu-programmer for OS X and AVR development tools. Looks like this is a good AVR toolkit for OS X. I’m not sure where you can find dfu-programmer, but you could always compile it from source if you want.
Creating the project:
Now, we’re back to a point where it doesn’t matter what OS you’re using. Open up Eclipse. Go to File->New->C Project. A window will pop up. If it’s not already expanded, expand the arrow next to “AVR Cross Target Application” and choose “Empty Project.” The toolchain selected on the right should be “AVR-GCC Toolchain.” Give your project a name and click Next. You’ll notice that Eclipse will create a Debug and Release configuration. You can leave them both on if you want, but I tend to remove the Debug configuration because it breaks some of the optimizations that avr-libc depends on (the delay functions, for instance). Click Next, and then you will be asked to name the microcontroller and clock frequency. The microcontroller is an AT90USB1287. The AT90USBKEY has an 8 MHz crystal and its provided programmed fusebits divide the crystal frequency by 8 to give you a clock rate of 1 MHz by default. However, we’re going to be disabling that prescaler at the start of our code and making it run at the full 8 MHz, so you should type “8000000” into the MCU frequency text box. Finally, click Finish.
If you left the Debug build configuration enabled, make sure that your currently-selected build configuration is the “Release” configuration. Right-click your project in the left column of the Eclipse window and choose Build Configurations->Set Active->Release to select Release. If you don’t do this, the delays won’t work (and you will get build warnings from avr-libc telling you to turn on optimizations or else the delay functions won’t behave as intended).
Now, we’re ready to create a simple project. Let’s blink the LEDs. The code will be very similar to some of my earlier microcontroller programming examples. Before we write the code, let’s do the research and find out what GPIO pins we will need to play with.
According to the AT90USBKEY hardware user guide, the LEDs (D2 and D5) are bi-color LEDs connected to PORTD:
- D2
- Red is connected to PORTD, pin 4
- Green is connected to PORTD, pin 5
- D5
- Red is connected to PORTD, pin 7
- Green is connected to PORTD, pin 6
They behave just like they are separate LEDs. So in effect, you have four LEDs available, although each pair of green and red LEDs overlap with each other and look kind of strange when they are both on at the same time. Anyway, this is all we need to know to get a simple program running. Let’s do it!
Create a new C file by right-clicking on your project in the left column of your Eclipse window and choosing New->Source File. Name your file main.c and leave the template as the “Default C source template.” Type (or copy/paste, if you’re not masochistic) this code into main.c:
#include <avr/io.h> #include <util/delay.h> #include <avr/wdt.h> #include <avr/power.h> #define LED_PORT PORTD #define LED_PORT_DDR DDRD #define LED_PIN PIND #define LED1_RED (1 << 4) #define LED1_GREEN (1 << 5) #define LED2_RED (1 << 7) #define LED2_GREEN (1 << 6) int main(void) { // In case the watchdog timer is enabled, disable it. wdt_disable(); // Make sure the clock prescaler is disabled (divide by 1) clock_prescale_set(clock_div_1); // Set the LEDs as outputs and turn them all off LED_PORT_DDR |= LED1_RED | LED1_GREEN | LED2_RED | LED2_GREEN; LED_PORT &= ~(LED1_RED | LED1_GREEN | LED2_RED | LED2_GREEN); // Turn on LED1's red output and LED2's green output LED_PORT |= (LED1_RED | LED2_GREEN); while (1) { // Wait and then toggle all four LEDs _delay_ms(1000); LED_PIN = LED1_RED | LED1_GREEN | LED2_RED | LED2_GREEN; } }
Now, compile the program by going to Project->Build All. This command actually builds all open projects, but since this is the only project we have open, it will work. You may see some weird errors about DDRD and PORTD being undefined — if so, it’s probably Eclipse whining about it rather than the compiler. Rebuild the index by right-clicking on your project and choosing Index->Rebuild — hopefully those errors will go away. Anyway, you should have a .hex file inside the “Release” folder ready for flashing.
I want to share a quick note about this code before we get to the rest of the flashing. Did you notice that I write to the PIND register to toggle the LEDs inside the while loop? Normally, this register is used for reading the state of port D’s input pins, and you would use PORTD to change the state of the output pins. AVRs have a cool feature — if you write a “1” to a bit in an AVR’s PINx register, it will actually toggle the value of the corresponding bit in the PORT register. Any bits that are 0 are unaffected. It’s just a handy little shortcut that probably doesn’t apply to other microcontrollers, but it does work on several different AVRs that I have used. The code generates results identical to (but is more efficient than):
LED_PORT ^= LED1_RED | LED1_GREEN | LED2_RED | LED2_GREEN;
Enough about that — back to flashing!
Flashing your code to the board:
If all went well, you are ready to test your newly-created firmware project. First of all, let’s get your AT90USBKEY board into its bootloader. Connect the board to your computer. Now, while holding down the HWB button on the board, press the RST button on the board. This forces the AT90USB1287 to boot into its supplied USB DFU bootloader. Alternatively, you could also just hold down the HWB button while plugging the board into your computer.
Now, we need to break off depending on which OS you’re using again:
If you’re using Windows:
Open up Flip (you installed it already, right?). Click the leftmost icon in the toolbar (looks like a DIP chip) and select AT90USB1287 as your target device. Now, click the second icon from the left (looks like a USB cable) and choose USB. A dialog box will come up–click Open. All of the buttons in the Flip window should be enabled now. You’ve made contact with the bootloader! Click the third icon from the right (looks like a book with an arrow pointing down) to load a hex file to download to the device. Navigate to your Eclipse workspace and find the YourProjectName.hex file. It should be in the Release folder inside your project’s folder. This will load the .hex file into Flip’s buffer, but won’t program it yet.
On the left side of the Flip window under Operations Flow, make sure Erase, Program, and Verify are checked. If they are, click Run. If all goes well, the status bar in the bottom of the Flip window should say “Verify PASS.”
If you’re using Linux:
This should be pretty easy, assuming you have already configured dfu-programmer correctly. Type:
dfu-programmer at90usb1287 erase dfu-programmer at90usb1287 flash /path/to/my/projectfile.hex
(Of course, replacing /path/to/my/projectfile.hex with the path to your hex file.) That’s it!
If you’re using Mac OS X:
Once again, I’m lazy. You should be able to use the same directions as Linux if you can get dfu-programmer up and running.
Running your code:
You have now successfully programmed your firmware onto the board. Press the RST button on your board and watch as your program runs and toggles the LEDs every second. Easy, right? If you want the original firmware that came on the board, you should be able to get that back by flashing one of the provided .a90 files from Atmel’s AVR287 example. To be safe, it might be wise to back up the supplied contents of the mass storage device that the board’s default firmware creates before loading your custom firmware.
Conclusion:
I have now shown you how to get a simple program running on the board. Download LUFA, play around with it, and see what you can create! Atmel also provides some USB libraries, although I haven’t played with them.
As far as this board goes, it’s fantastic. It gives you plenty of fun devices play with. You can learn about GPIO pins with the LEDs (outputs) and the joystick (inputs), you can learn about analog-to-digital converters (ADCs) with the temperature sensor, you can learn about SPI with the two serial flash chips, and you can of course learn about USB.
Pros:
- It’s really easy to get running without needing any external programmer hardware. It’s basically unbrickable.
- They provided some handy (exotic?) cables to give you the opportunity to play with the board as either a USB host or device.
- Atmel made creative use of the USB capability by providing all documentation and software on the device itself as a mass storage device that appears when you plug it in.
- It has awesome community support because it’s an AVR.
Cons:
- The DFU flashing software (particularly Flip) is kind of confusing and annoying to use. It’s a lot more convenient to develop with JTAG or ISP because you don’t have to physically mess with the board whenever you want to write a new program to it. It would also be nice to integrate this flashing with Eclipse. I’m sure it’s possible with a custom run configuration and a script.
- They brought the other port pins out to very tiny headers. It appears that headers would be difficult to solder, and it would be a challenge to find the correct header part for soldering. It would be nice if they used standard 0.1″ pitch headers instead, although that would obviously come at the expense of a larger board size.
You can buy an AT90USBKEY at Newark. Thanks again to Newark/Farnell for the opportunity to review this cool little development kit!