Showing posts with label USB. Show all posts
Showing posts with label USB. Show all posts

2011-03-10

Atmel AVR USB - First app

Time to get our toolchain installed then. You'll see plenty of posts mentioning the need to install WinAVR around, but with the latest toolchain from Atmel, it looks like a separate installation of WinAVR has become a thing of the past, and we won't actually need to install anything but latest official Atmel toolchain, which is called AVR Studio.

Now, Atmel did the smart thing here: They picked up the Visual Studio 2010 base from Microsoft which they wrapped around avr-gcc and avr-libc. We've come a long way from substandard proprietary toolchains...

So off you go to download AVR Studio 5 (free, but registration required). Installation takes a little while but is a no brainer. Sadly, no Flip integration is provided yet, so we'll have to generate a .hex and still use Flip manually to transfer the files. On the other hand, it should be possible to port the libusb 1.0 and commandline based dfu-programmer to Windows, to provide a flashing tool that integrates with AVR Studio.


Creating a project for Minimus USB

Alrighty, let's create our first LED blinking app then. Creatively, I'm going to call it 'Blinky'.
In AVR Studio, click "New Project" and use the "AVR GCC", "Empty AVR GCC Project" template (which should be selected by default). The Minimus USB, or any AT90USB162 based board don't seem to exist in the Atmel/User Boards lists, so don't bother trying to pick a template there. Change the default Name to 'Blinky' and click OK.
On the next screen, in the Device Family, select "megaAVR, 8-bit", and pick up AT90USB162 (or any other Atmel chip you might be using). Click OK and you're done. AVR Studio will even create a source template for you, how nice!

One thing you'll notice when compiling a new project is that the default settings are not to generate a .hex. To fix that, simply right click on the project, in the solution explorer, and in the Build tab, on the "Generate Files" line make sure the ".hex" checkbox is set (for both Release and Debug).


Blinking code

Armed with the knowledge of where the LEDs and HWB button are connected (PD5 and PD6 for the LEDs, PD7 for HWB), let's write us some code to blink the LEDs. We might as well look at the samples for inspiration.

First thing we'll do, since we need to add some delay when toggling the LEDs, is use some of the handy functions from the avr-libc. util/delay.h provides a _delay_ms() call that should do the trick. The only thing is you need to define F_CPU to your board's frequency, before the #include, for the delay calls to be accurate. The Minimus USB uses a 16 MHz Xtal, therefore our blinking code can be:

#include <avr/io.h>
#define F_CPU 16.000E6
#include <util/delay.h>

void init_ports(void)
{
    PORTB = 0b00000000;
    DDRB = 0b00000000;

    PORTC = 0b00000000;
    DDRC = 0b00000000;

    PORTD = 0b00000000;
    DDRD = 0b01100000;      // Set LEDs as output
}

int main(void)
{
    init_ports();
    
    while(1)
    {
        if (PIND & 0b10000000) {
            PORTD = PORTD & ~0b01000000;
            PORTD = PORTD |  0b00100000;
            _delay_ms(200);
        
            PORTD = PORTD & ~0b00100000;
            PORTD = PORTD |  0b01000000;
            _delay_ms(200);
        } else {
            PORTD = PORTD | 0b01100000;
        }
    }
}


The (loose) PIND & 0b10000000 test is added to turn off both LEDS when HWB is pressed.This should compile alright.
Note that you might want to pay attention to the warnings generated when compiling (on the "Errors" tab), especially the one that says, when using delay.h in Debug mode:
"Compiler optimizations disabled; functions from won't work as designed". Using delay.h will be fine for Release, but if you find that your delays are off in Debug, don't be surprised.


That friggin' watchdog timer

OK then, let's use Flip to transfer the hex, then click "Start Application" and have a satisfied look at our red and blue LEDs alternating... except they don't! Only the red LED blinks, and definitely not at 200 ms. AVR Dude, what the hell?!?

Oh, and it gets better, if you unplug the board, and plug it back, then suddenly everything works. What's going on here?

Part of the answer can be found in the Flip user guide:


4. What is the difference between starting the application with the Reset box checked off or not?
• If you start the application with the Reset box checked, the device will start after a Watchdog reset and this watchdog will remain active. You need to disable the Watchdog in your application. Resetting the device, ensures there is no side effect from resources used by the boot-loader before starting the user application.

Lo and behold, if you uncheck the Reset box and reflash/restart the app, everything works as expected. Of course, if you're unaware that the Flip Reset box is the culprit, you're bound to run into this issue, eventually figure out that it has to do with the WatchDog, and want to disable it in your program, so we might as well take care of that little bugger.

Now, I found that the code samples from all the LED blinkers out there, that are supposed to disable the watchdog, as well as the watchdog disable code from the AT90USB162 datasheet didn't work at all. Even including <avr/wdt.h> and calling wdt_disable() alone didn't work (but at least you could do something like wdt_enable(WDTO_8S); to make the delay before reset much longer, in order to give you a chance to issue a wdt_reset() before it expires).
There have been a few discussions on the AVRFreaks forums related to this, and the first way I found to disable watchdog and make it work with a Minimus USB, for programs transferred using Flip with Reset enabled, was the one provided by curtvm's from this post.

If you include wd.h and call WD_DISABLE(), the Watchdog timer finally gets disabled. But then, looking at what the LUFA samples were doing, it appears that using avr/wdt.h also works, provided that you issue and MCUSR &= ~(1 << WDRF) before calling wdt_disable().
Thus, our final code, which now works regardless of whether the Watchdog is initially enabled or not, becomes:
#include <avr/io.h>
#define F_CPU 16.000E6
#include <util/delay.h>
#include <avr/wdt.h>

void init_ports(void)
{
    PORTB = 0b00000000;
    DDRB = 0b00000000;

    PORTC = 0b00000000;
    DDRC = 0b00000000;

    PORTD = 0b00000000;
    DDRD = 0b01100000;      // Set LEDs as output
}

int main(void)
{
    MCUSR &= ~(1 << WDRF);
    wdt_disable();
    init_ports();
    
    while(1)
    {
        if (PIND & 0b10000000) {
            PORTD = PORTD & ~0b01000000;
            PORTD = PORTD |  0b00100000;
            _delay_ms(200);
        
            PORTD = PORTD & ~0b00100000;
            PORTD = PORTD |  0b01000000;
            _delay_ms(200);
        } else {
            PORTD = PORTD | 0b01100000;
        }
    }
}

Tested and confirmed. Great, now we're all set to produce more interesting AVR USB apps, like ones using LUFA for instance...

Atmel AVR USB - Let's get cracking!

Recently purchased a Minimus USB clone as these have gotten relatively cheap thanks to all the current PS3 hacking (Disclaimer: I don't have a PS3 and don't care much about what other non-development use these boards are also being targeted at).

All this to say that getting an Atmel AT90USB162 based board, or similar, has now gotten cheap enough that you might as well get one, if you're planning to play with USB, using Atmel AVR chips.

The following post assumes that you're completely new to AVR development, and aims at helping you getting started. I'll assume the use of a Minimus USB board and Windows, for the rest of this guide.


Flip... flops?

Except for the bootloader, the flash should be pretty much blank on arrival, yet you probably found a test program that tests the LEDs or something, that you want to run to confirm that the board is good. There's an USB bootloader in there, to take care of the flashing, but to be able to use it you'll need the following:
  1. the flashing application itself, which is Java based and called "Flip"
  2. an USB driver for the application to use
If you head to the Atmel website you'll find the Flip 3.4.2 downloads. If you don't have Java installed already, you should obviously pick the one that has the JRE included, and install the application. That takes care of step 1, but we still need some drivers to have the app communicate with the device. These drivers are located in "C:\Program Files (x86)\Atmel\Flip 3.4.2\usb" (If you used the default installation path).
Now the good news here is that they are using the libusb-win32 Windows driver (smart choice!). The bad news however is that, as per Flip 3.4.2, they are not using the signed libusb0.sys drivers, or anything WHQL. Therefore, if you're running on Windows 7 or Vista x64, the driver installation will fail. Ouch!
Thankfully, you don't have to use the Atmel driver files from the Flip application, and the latest libusb-win32 ones, which are signed, will work just fine. The easiest way to install them then is to download the latest libusb-win32 binary release, extract the zip and then run the inf-wizard.exe you'll find in there, with your device plugged in. Or you can also download the latest Zadig.exe, select Options->Advanced Mode, and change the target driver from WinUSB. which is the default, to libusb0.

Once the driver is successfully installed, you can run Flip, and if you press Ctrl+U to bring the USB communications menu (or go to Settings -> Communication -> USB), you should now be able to open the device with Flip properly identifying your chip. Groovy.

I also should point out that a more detailed guide (with pictures) on how to use Flip with AT90USB chips is also available from Atmel.


Bootloader mode or not bootloader mode: that is the question

One item that might be of interest to you, if you're completely new to using bootloaders to reprogram the flash, is that once you successfully transfer an application to the flash and get it to run, the bootloader will obviously no longer be accessible, and if your app does not do anything with USB, it will be innaccessible from your computer.

So how do you get back to USB bootloader mode for reflashing? Simple:
Just make sure the HWB button is pressed when you press the RST button.

So in essence the method to enter the bootloader is 1. Press RST, 2. press HWB, 3. release RST, 4. release HWB - easy.
This of course assumes that the Hardware Boot Enable Fuse (HWBE) has been set on the board and that PD7 is connected to a HWB button. For more info, see chapter 23.5 of the AT90USB162 datasheet.


Is it Blinky? Or is it just Clyde?

"Enough of these preliminaries, let's get these LEDs blinking already!"

Alright, I hear ya. But if you assume that any LED blinking app listed on the Minimus USB website would work, you assumed wrong. The only one that actually successfully blinks the LEDs is the one you will find in the minimus_led_test.rar, and even that one, depending on how you run it, might not actually blink the LEDs because of how its program, but because of the watchdog timer (more about this in the next post).

So, provided you extracted the minimus_led_test.hex, and you have Flip in programming mode, the way to go is:
  1. File -> Load Hex file and pick up the .hex. The FLASH Buffer information will now be populated
  2. Click the 'Run' button, which will erase, program and verify the flash (default options). Note that if you try to flash without erasing first, you will get a "Device protection is set" error. You always need to erase the flash first
  3. Click the "Start Application" button
Your LEDs blinking yet? Good. Now let's get ourselves sorted to write our own LED blinker app.
We'll setup a toolchain that generates Intel .hex files, and then flash these files using the same method above.

2010-08-13

Schematics for a PIC 18F2550 based USB demo board


Click on the image above for the PDF schematic for a Microchip PIC 18F2550 based USB demo board, with a TTL serial port (also in .ai format).

Or, since I'm reusing their design and also have been using one of their cheap PICKit2 Kit board, I'll mention that you can also buy a more elaborate ready to assemble version of the above demo board from fun4diy.com, that doubles as a PICKit2. Note however that if you use that PICKit2 "Kit" and want serial I/O, you'll have to modify the board a little (but you can use the unused U4 pins for that).

If you're testing USB, such a demo board is very convenient to have, and most of the PIC 18F4550 firmwares you'll see can be easily ported to 16F2550. I'll try to post more about that when I get a chance.

2010-06-07

Preventing USB devices with different serials to be seen as separate devices

Once again, I have to give props to Xiaofan:

The following is quoted from a USB-IF forum post (the link is now invalid)
http://www.usb.org/phpbb/viewtopic.php?p=33850

"Win2000/XP has a way to ignore the serial number.
This is copied form an AppNote I wrote:
-------------------------------------------------------
Ignore serial number in Win2000 / XP In Windows 2000 and XP,
there is a way to ignore the serial number for a certain device.
This is not recommended in general, but there are reasons to do so.

This is the registry key
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\UsbFlags]
The global way: The entry below does enable the serial numbers despite
its name! It is already there after a fresh installation.
GlobalDisableSerNumGen = 1
We recommend keeping the above setting unchanged.

Now here is the individual way. Create an entry under the
above ...\UsbFlags key. The name must start with "IgnoreHWSerNum"
followed by the vendor and product ID of the device. The value for the
entry is 1 for disable.
Example:
IgnoreHWSerNum0536016A= 1
Our vendor ID (VID) is 0536 (hex), the product ID (PID) depends
on the interface you choose.