Welcome to Pete Brown's 10rem.net

First time here? If you are a developer or are interested in Microsoft tools and technology, please consider subscribing to the latest posts.

You may also be interested in my blog archives, the articles section, or some of my lab projects such as the C64 emulator written in Silverlight.

(hide this)

Getting Started with AVR Studio 5

Pete Brown - 05 November 2011

As much as I like the .NET Micro Framework, and especially the .NET Gadgeteer line, I've been itching to try a little C/C++ for specific functions on boards. Consider things like chip controllers and stuff to offload work from the main micro controller, much like all those chips on your PC motherboard are doing to help the CPU. Generally, this is not a job for the .NET Micro Framework, although it can still be the main brain of the system.

There are lots of different types of microcontrollers out there, with the big three being ARM (which many vendors/manuifacturers license), AVR (Atmel only) and PIC (Microchip technology chips that have been around forever).

For playing around at the moment, I chose an AVR MCU on a test board. I haven't committed to any particular MCU for any projects yet. My main criteria is simply that I be able to code in C/C++ and not be forced to use assembly unless I want real optimization of a specific feature.

I've ordered a few boards lately, but the first one to arrive was the MikroElektronika "Ready for Xmega" board. This is a great little $35 board which includes the ATxmega128A1 (MPU datasheet). The ATxmega128A1 MCU has, according to Atmel:

  • Up to 32MIPS speed (at 32 MHz)
  • Low power 8/16 bit architecture
  • 128KB flash memory for storing the program
  • 2KB EEPROM for the boot section
  • 8KB SRAM memory
  • 32 registers
  • External bus interface for up to 16MByte SRAM and 128Mbit SDRAM
  • 78 IO pins
  • 32kHz Real-time Clock
  • Eight 16 bit timers
  • 16 bit Real time counter
  • 1.6 to 3.6v at 0-12MHz
  • 2.7 - 3.6v at 0-32MHz
  • Four two-wire interfaces
  • Four SPI peripherals
  • Eight USARTs
  • AES and DES Crypro Enginer
  • Two 12 bit analog to digital converters with 8 inputs each
  • Two 12 bit digital to analog converters (1 continuous or two sample and hold outputs each)
  • bunch of other stuff :)

FWIW, the MPU is also pretty buggy according to all the posts I've read and the big list of workarounds in the data sheet. I think it'll do, though. Here are a few photos of the board on my workbench

image

image

The board adds USB bootloader-based programming, as well as optional JTAG or PDI programming. For those of us used to Netduino, Arduino and the like, the bootloader-driven USB approach will feel the most familiar. For folks who want to just do this on a breadboard, there are other types of programmers you can use (for DIP packages, anyway, the surface mount ones need a board of some type, if only a breakout board)

Before I could do anything with the board, I needed to solder on the headers. The board breaks out each pin to a pair of headers, and also includes dedicated headers for JTAG and PDI programming. Here are some photos:

image

image

The headers aren't the tallest things on the board, so when soldering, you need to tack them on; you can't just flip the board on the table and use gravity to help you.

The way I do it is to tightly hold the header to the board with thumb and forefinger on my left hand (not touching any pins I'm about to solder!), then pick up a blob of solder with the soldering iron, and wipe it across the solder pad and pin on the back just enough to hold the pin in place. You're not looking for a good connection like you'd get in a two-handed operation, you want just enough to hold it in-place for a few minutes. On headers like these, I do two pins total on each header, in opposite corners. I then solder the rest of the pins on the header, then come back and re-solder the two tacked pins to get a good connection.

Now for some programming.

AVR Studio

AVR Studio is Atmel's free development environment for coding for their 8 and 32 bit AVR micro processors. AVR Studio 5 uses the Visual Studio 2010 Isolated Shell for the IDE. This is a product that doesn't get a ton of attention in the developer community, but makes it easier for other companies to quickly create developer solutions for their own products.

In this case, it is Atmel AVR Studio 5, which uses the GCC toolchain for the compiler, and some additional tools for actually sending bits down to the microcontroller.

Installation

The installer walks you through several different install steps, including the Visual Studio Shell, the USB driver, and the AVR tools themselves.

image

Hey, this looks pretty familiar! The Visual Studio Shell setup is similar to the regular Visual Studio setup.

image

Once the shell and USB drivers are installed, you'll get the setup for AVR Studio itself.

image

The AVR toolchain consists primarily of GCC tools.

Running AVR Studio

Now, because I have VS2010 SP1 on my machine for normal development, and AVR Studio 5 doesn't install SP1 by default, I need to re-apply SP1. How did I know? This is the message I got when I ran AVR Studio:

image

The AVR Freaks forums had some folks asking about SP1 and whether it was ok to install. General consensus was it's fine and adds some improvements to the shell, but wasn't necessary if that's all they used Visual Studio for. For those of us who live in Visual Studio all day, especially SIlverlight developers, SP1 is definitely required. So, off I go to repair its installation.

image

Unfortunately, it had to roll back due to the interim build Silverlight stuff I have, so I had to go uninstall the Silverlight 5 bits then re-install them after the SP was installed. No worries. It's not like I'm trying to wrap up the last two chapters of a Silverlight book right this very moment or anything ;)

Rolling back is not a fast process, even on an SSD, so you may want to take some precautions ahead of time. For example, uninstalling Silverlight first.

Oddly enough, after the rollback, AVR Studio and everything else worked, and shows as running SP1. Not sure how I feel about that but "Comfortable" isn't it.

Running AVR Studio Take 2

This looks familiar, but now with a cool ladybug icon. AVR Studio is working just fine.

image

For grins, I opened up regular visual studio and verified that I could still build Silverlight 5 projects as earlier. Yep. No problems.

Hello World: Yes! Another BlinkenLed Project!

This is quite a bit lower level than what I normally do with devices like the Gadgeteer. That, plus my lack of experience with this hardware has made me set my sites for "Hello World" really low :) In fact, it will be a success if I can simply figure out how to compile and deploy code to the board.

AVR Studio comes with a ton of sample projects. They also have project types which target their own demo boards. Because I'm using a third-party board, I had to pick "user board" as the type of project. I was then presented with a list of MCUs to pick from, via a drill-down.

image

Once I got to the XMEGA family, I picked the one that is on this board, the 128A1. AVR Studio presented helpful links for that processor over on the right. Once you've selected your processor, the targets for the project will be correctly set via the toolchain entries in the project properties.

You'll then be tossed into the code editor with the basic outline of a program already there.

image

What you do at this point is, of course, up to you. I had no idea, so I started hunting around on the avrfreaks.net forums until I found some tutorials. Between that and (mostly by) looking at the include files (on my machine: C:\Program Files (x86)\Atmel\AVR Studio 5.0\AVR Toolchain\avr\include\avr ), I was able to put together some of the important things:

  • iox128a1.h contains the IO definitions for the MCU on this board. There are different definitions for each MCU, but they try and keep them somewhat source compatible
  • The code I found for the ATTINY and other Atmel processors, using macros like DDRC, doesn't work on this chip. There are different macros (maybe this is an AVR Studio 5 thing?)
  • Pins are grouped into ports.
  • When performing output operations, you must first set the I/O flags for the pins on the port. You do this one entire port at a time
  • You need to specify the CPU speed you want to run at using the F_CPU define before all other includes. This speed can be lower than the rated speed of the MPU.

I still had the DerBlinkenLed project on my breadboard from the Gadgeteer project, so I pulled out the Gadgeteer header and plugged in the right pins for the Atmel board.

Here's the first version of the program I wrote. DON'T USE THIS, AS IT DIDN'T WORK.

/**
* main.c
*
* ATxmega128A1 targeted "Hello World" example - Pete Brown
* THIS IS A NON-WORKING EXAMPLE. SEE LATER EXAMPLE
*/

#ifndef F_CPU
#define F_CPU 32000000UL // 32MHz clock speed
#endif

#include <avr/io.h>
#include <util/delay.h>

int main (void)
{
// not doing anything really with the board, so I commented this out
// and removed the <include <asf.h> from the top as I'm not using the framework
// board_init();

// set the directions for Port C.
// could also use the PORTC_DIR macro
PORTC.DIR = 0b00000001;

while (1) // loop forever
{
// PC0 pin is LSB of PORTC value. Could also use the PORTC_OUTSET macro. not sure of any perf difference
PORTC.OUTSET = 0b00000001;
_delay_ms(500);

// turn the port off (LED off)
PORTC.OUTSET = 0b00000000;
_delay_ms(500);
}
}

The problem with this listing is that the LED stayed on 100% of the time (or at least it appeared that way). I  didn't find that out until after deployment, however.

Deploying the application

You need the tools to create the hex file for you. By default, you get a .elf, but no hex. Go into the project properties, build tab, and select the option to generate .hex files. Rebuild at that point.

image

At this point, I had to insert the DVD that came with the board. They didn't have the same software available for download online as far as I can tell so I actually had to put a physical disc in my drive. That's roughing it!

What do you know? The DVD has example source code for working with this board. It's not for AVR Studio, but I can probably learn a few things from it.

In the end, the bootloader app wasn't actually on the DVD, it's on the web site. There's no installer for it, so you just need to save it someplace save and set up a shortcut to it. I recommend adding it to the external tools in Visual Studio er….AVR Studio, like this:

image

Run the program and select the correct COM port. I didn't have the board plugged in when I first started this, so it default to COM 1. However, I then plugged it in and clicked "Change Settings" and found COM9 to be the only option. I also recall seeing the board ID as COM9 when it installed the USB drivers.

Then, reset the board (little button on the left side of the board) and quickly (within 5 seconds or less), click the "Connect" button. It will change to "Disconnect" and you'll see the Connected message in the history window.

image

In my screen shot, you can see it took me a few tries to get within the time limit. I didn't realize there was a time limit until I read it.

I think browsed for the .hex file and clicked the "Begin uploading" button.

image

When it completed, I was instructed to reset the MCU (again, using the button)

image

At this point, the program ran, but the LED stayed lit all the time. Time to figure out why.

I knew it had to do with my code, because the LED was not lit in the factory default (empty) program.

So, I went back to the iox128a1.h file and looked at the definition of the PORT structure. I saw that it has a DIR as well as a DIRSET as shown here:

/* I/O Ports */
typedef struct PORT_struct
{
    register8_t DIR;  /* I/O Port Data Direction */
    register8_t DIRSET;  /* I/O Port Data Direction Set */
    register8_t DIRCLR;  /* I/O Port Data Direction Clear */
    register8_t DIRTGL;  /* I/O Port Data Direction Toggle */
    register8_t OUT;  /* I/O Port Output */
    register8_t OUTSET;  /* I/O Port Output Set */
    register8_t OUTCLR;  /* I/O Port Output Clear */
    register8_t OUTTGL;  /* I/O Port Output Toggle */
    register8_t IN;  /* I/O port Input */
    register8_t INTCTRL;  /* Interrupt Control Register */
    register8_t INT0MASK;  /* Port Interrupt 0 Mask */
    register8_t INT1MASK;  /* Port Interrupt 1 Mask */
    register8_t INTFLAGS;  /* Interrupt Flag Register */
    register8_t reserved_0x0D;
    register8_t reserved_0x0E;
    register8_t reserved_0x0F;
    register8_t PIN0CTRL;  /* Pin 0 Control Register */
    register8_t PIN1CTRL;  /* Pin 1 Control Register */
    register8_t PIN2CTRL;  /* Pin 2 Control Register */
    register8_t PIN3CTRL;  /* Pin 3 Control Register */
    register8_t PIN4CTRL;  /* Pin 4 Control Register */
    register8_t PIN5CTRL;  /* Pin 5 Control Register */
    register8_t PIN6CTRL;  /* Pin 6 Control Register */
    register8_t PIN7CTRL;  /* Pin 7 Control Register */
} PORT_t;

At first, I thought perhaps it was because I used DIR and not DIRSET, so I changed the code to use DIRSET rather than DIR. No change. That got me to thinking that it might be the actual .OUTSET that's the problem. So, I changed that to .OUT and deployed it.

Success!! Well, kind of. The LED now blinks, but very slowly. Clearly there's a problem with the clock speed here, as 500ms is coming out as around 7 seconds. Just to make sure it wasn't going into a low-power mode due to crappy USB power, I plugged in an external supply…and got the same result.

So, I looked around a little more and saw that there's an enum for system clock selection:

/* System Clock Selection */
typedef enum CLK_SCLKSEL_enum
{
    CLK_SCLKSEL_RC2M_gc = (0x00<<0),  /* Internal 2MHz RC Oscillator */
    CLK_SCLKSEL_RC32M_gc = (0x01<<0),  /* Internal 32MHz RC Oscillator */
    CLK_SCLKSEL_RC32K_gc = (0x02<<0),  /* Internal 32kHz RC Oscillator */
    CLK_SCLKSEL_XOSC_gc = (0x03<<0),  /* External Crystal Oscillator or Clock */
    CLK_SCLKSEL_PLL_gc = (0x04<<0),  /* Phase Locked Loop */
} CLK_SCLKSEL_t;

So that must mean there's some way to set that.

So I found this thread on avrfreaks that happens to mention that by default, the clock is set to 2MHz. So, I set F_CPU to 2MHz and…it worked! Here's the working code:

/**
* main.c
*
* ATxmega128A1 targeted "Hello World" example - Pete Brown
*
*/

#ifndef F_CPU
#define F_CPU 2000000UL // 2MHz default clock speed. Can be 32MHz once select clock
#endif

#include <avr/io.h>
#include <util/delay.h>

int main (void)
{
// not doing anything really with the board, so I commented this out
// and removed the <include <asf.h> from the top as I'm not using the framework
// board_init();

// set the directions for Port C.
// could also use the PORTC_DIR macro
PORTC.DIR = 0b00000001;

while (1) // loop forever
{
// PC0 pin is LSB of PORTC value. Could also use the PORTC_OUT macro. not sure of any perf difference
PORTC.OUT = 0b00000001;
_delay_ms(500);

// turn the port off (LED off)
PORTC.OUT = 0b00000000;
_delay_ms(500);
}
}

While 2MHz is faster than all the Commodore 64s I have sitting around in my office, I'm not quite satisfied with that. It works, but I'm not using every bit of juice available (not that I need to in this case, but I want to know *how*). That said, it will need to wait for next time.

Next Steps

So what do I intend to use this knowledge for? Well, there are some things that the .NET Micro Framework isn't well-suited to doing, such as real-time signal/data processing. As I mentioned in the opening, I want to use these as helper/co processors to handle specific tasks that can be coordinated by NETMF. Why combine the two and not do everything in C? Well, at least for the foreseeable future, NETMF has better high-level functions for things that don't require the extreme speed. Stuff like user input and file IO and whatnot. Just like my Core 2 in my desktop isn't great at graphics processing so I use an nVidia card, I'll use something like the XMEGA for hardcore signal processing.

       
posted by Pete Brown on Saturday, November 5, 2011
filed under:        

7 comments for “Getting Started with AVR Studio 5”

  1. Petesays:
    @Jeeshen

    None of the PIC controllers run netmf. Depending on what you want to do, I would evaluate these controllers:

    .NET Gadgeteer:
    http://10rem.net/blog/2011/10/24/getting-started-with-the-net-gadgeteer---part-1-background-setup-and-hello-world
    http://10rem.net/blog/2011/10/30/building-a-net-gadgeteer-compatible-hardware-and-software-module-der-blinkenled

    Netduino and Netduino Plus
    http://netduino.com

    FEZ Panda II
    http://www.ghielectronics.com/catalog/product/256/

    There are many others, but most of them are pretty expensive. The Panda II has a nice starter kit you can get in case you'd rather plug and play as opposed to using a breadboard.

    Pete
  2. carltonsays:
    I have been dabbling with AVR's as well, I wish I had more time to play around with them. I'm just curious, what made you choose AVR/Atmel over PIC? It seems that most people gravitate to the PIC line. Personally I like the AVR much better so I was glad to see you jump on board with them.
  3. K Scharfsays:
    The OUT macro writes the bits you set to the port, IE it changes the port bits to what you write.
    The OUTSET macro sets the corresponding bits, writing OUTSET with a zero argument does NOTHING.

    You could blink the led with an OUTSET followed by an OUTCLR with the same argument. OUTCLR clears the corresponding bits.

    There is also an OUTTGL that toggles the corresponding bits. In other words, OUTSET performs an OR of the current port with the argument, OUTCLR performs and AND of the current port bits with the ones complement of the argument, and OUTTGL performs and XOR of the current port bits with the argument.

Comment on this Post

Remember me