Tips, tricks and highlights for the AtXmega micro controller

AtXmega micro controllers are quite special. Even If you are familiar with standard AVR micro controllers like the AtMega 168 (used in arduino), there are many aspects that can discourage you from migrating to Xmega. Via this article, I want to tackle some key issues that made me struggle the first time I used an AtXmega, and the solutions and workarounds I came up with or that i have simply found in datasheets and application notes. Even if the transition was tough, it is totally worth the trouble. Now that i made it safely into AtXmega world, I think it’s a wonderful device and i am using it for various clients/projects.

Important note: All code snippets provided in this article are tested with AtXmega A3 family of micro controller. We didn’t try them with other sub-families of the AtXmega family of micro controller. Some modifications may be needed to adapt to your specific micro controller.

When do you chose to use an Xmega over a regular mega AVR?

Mainly when you need to go as fast as 32MHz and when you need a lot I/O. Any by a lot of I/O i don’t only mean GPIOs (General Purpose Input Output). I also mean SPI, TWI (I2C) and UART ports. That is also true ADC and DAC. You also have to consider price: Obviously Xmega will cost more than mega AVRs.

Some getting-started notes for the AtXmega

AtXmega firmware can be developped in AVR Studio 4 or 5 IDE (or even AVR Studio 6 but I didn’t test it yet).  Make sure you downloaded and installed the latest version of winavr. As with any other avr, you just need to #include <avr/io.h> to gain access to all SFRs (special function registers).

This “io.h” file will just select the correct header file according to the mcu that is defined in your project properties. If you are using the ATXMEGA256A3B for example, it will be the file “iox256a3b.h”. You can open it from the directory “c:\winavr-xxxxxxxx\avr\include\avr\” to find all registers definitions. The most basic thing you will want to do is to control I/O ports and you can do it like that:

PORTA_DIR = XX;    // set port A data direction
PORTA_OUT = XX;    // Out put XX on port A
XX = PORTA_IN;    // read the value of port A in XX

The best way is to dig your way through the Xmega manual and the io header file corresponding to your mcu. I totally dis-recommend to use atmel’s ASF. I respect ATMEL for many things, but this ASF framework is not one of them. I believe it is a total failure due to its unfriendliness. I think they tried to build some kind of hardware abstraction layer (HAL). If a HAL is usually used for ARM 32-bit MCUs, personally it don’t think it is an interresting option for 8/16 bit micro controllers.

Another big difference with regular Mega AVRs, is that in most cases you don’t need to mess around with fuse bits (eliminating – by the way – the chance to lock an MCU into an unknown state, which has happened one day or another to any atmega developper). The clock for example is set with in the code as we will see later in this article.

Xmegas are programmed through a PDI interface or JTAG. We use Atmel’s JTAG MKII, but i am sure the world is full of clones.

Identical peripheral functions

One of the things I like the most about Xmega is that all peripheral of the same class are totally identical. Do you remember when you had to reconfigure the timer/counter modure and redo all the calculation just because you switched from TC0 to TC1? Well you no longer need to worry about that with Xmega : all timers share exactly the same registers structure, and that’s true for all peripheral functions like UARTs, SPIs and TWIs. This unique feature make it very easy to port a timer configuration from one timer/counter module to another with very little effort. For example this piece of code :

//Configure Timer Counter E 0
TCE0.CTRLA = TC_CLKSEL_DIV4_gc;
TCE0.CTRLB = TC0_CCAEN_bm | TC_WGMODE_SS_gc;
TCE0.PER = 100;
TCE0.CCA = 50;

Can be modified by only changing ‘TCE0′ to ‘TCD0′:

//Configure Timer Counter D 0
TCD0.CTRLA = TC_CLKSEL_DIV4_gc;
TCD0.CTRLB = TC0_CCAEN_bm | TC_WGMODE_SS_gc;
TCD0.PER = 100;
TCD0.CCA = 50;

This is not possible with regular mega AVRs where the 3 timer/counter modules are all wired differently.

Accessing the Xmega I/O ports with assembly ‘IN’ and ‘OUT’ opcodes

For some application, I really like to embed some assembly code into my main C program to boost the execution speed of some parts. this is very useful when you need to control timing down to the single clock cycle. At some point, you will want to use the ‘IN’ and ‘OUT’ opcodes for their 1 cycle execution time. If you try to use that technique with atXmega, you will have to learn a new trick. in AtXmega, IN and OUT op codes cannot access I/O PORT like PORTA and PORTB directly. Instead it can access ‘virtual ports’. Xmega has 4 virtual ports that can be mapped to any I/O port of the micro controller.

For example, you can map port A and port B to virtual ports using this C line code:

(see page 143 of Xmega A manual for more informations)

PORTCFG_VPCTRLA = 0x10; //Port0 = PORTA, PORT1 = PORTB

and then access the ports with inline assembly as in this example:

asm volatile(
    "cli"                                "\n\t"
    "L1: in r24, 0x0012"        "\n\t" //read portA_in (mapped to port0) to r24
    :
    : "r24" //declare that we are using r24
);

Let the Xmega run at its maximum 32 MHz clock.

If you’re like me, you’ll want to push a device to its limits right away. This piece of init code direct the Xmega A3 to switch to its 32MHz internal RC clock:

volatile uchar i;

OSC.CTRL |= (1<<1); //enable RC32M
//wait for 32M clock to stabilise
i=0;
while(--i){;}

CCP = 0xD8; //Allow Protected IO changing
CLK.PSCTRL = 0; //set prescaller to 1 (no division)

CCP = 0xD8; //Allow Protected IO changing
CLK.CTRL = 1; //Select the 32MHz RC clock

DFLLRC32M_CTRL = 1; //activate auto calibration

The line “CCP = 0xD8;” just enter a password (0xD8) to allow changing sensitive system registers like the clock related registers.

The line “while(–i){;}” simply forces the AtXmega to wait for 255 clock cycles. This is usually enough for a clock to stabilize and be usable.Of course, that’s not the most elegant way of doing it, but i wanted to keep things simple for a start!

Careful about port B and port F!

I remember loosing almost a whole day because of what i am going to share with you! PORTB of the AtXmegaA3 micro controllers also hosts the JTAG interface. By default the JTAG interface is enabled, rendering the higher 4 bits of PORTB unusable, or even worse, causing the mcu to restart each time you apply some signals to it. If you’re not using JTAG (then you’re using PDI) to program the micro controller, then do yourself a favor and dis-activate it with the following code:

CCP = 0xD8; //Allow Protected IO changing
MCU_MCUCR = 0x1;

PORTF can also be tricky in the AtXmega. Depending on the micro controller you’re using, PORTF may have a missing 5th bit. That is, you only have PF0 to PF4 and PF6 to PF7, but no PF5 pin. This also is something I didn’t catch the first time i read the datasheet, and it did cost me a couple of hours and PCBs i had to throw away: I don’t want that to happen to you!

Conclusion

There are many other ‘major’ differences between atmega and atXmega micro controllers, like the fractional BAUD rate generator for Xmega’s UART ports, the DMA, or the event system which i may discuss in another article if it’s requested by the reader. However you can dig your way through the datasheet to get all the answers you need.

Don’t hesitate to leave comments and let me know if you need any more info on a related subject.

Comments ( 10 )

  • Steve Germann says:

    Thank-you for creating this page. And thank-you especially for using hex values, with comments, in the program, rather and abstruse _bm codes which just take time to look up, or worse, require a project that includes an entire tree of hundreds of include files.

  • Ponder says:

    I’m a hardware designer and need to program in assembly for maximum control and timing reasons. I’m trying to get the USART on the XMEGA to work in the simulator and can’t seem to get a value written to USARTF0_DATA. I can write to the other registers for setting the baud rate…. and see the results in the AVR Studio simulator but not in the USARTF0_DATA register. Can you help me by sending me the assembly code for writing out a byte through the USART F0?
    These lines seems to work:
    ldi r31,$22
    sts USARTF0_BAUDCTRL,r31
    ;$22 appears in the USARTF0_BAUDCTRL register

    but this one doesn’t:
    ldi r31,$22
    sts USARTF0_DATA,r31
    ;the DATA register in the simulator never changes from 0.

    Can you help me?
    Thank you very much for any support you can give me.

    • Ibrahim KAMAL says:

      Hmmm…. I am not sure, you’ll have to check with the datasheet, but i think that USARTF0_DATA is a special register. The Rx and Tx registers are mapped to the same memory location. When you write to USARTF0_DATA, it goes to Tx register, when the debugger (or anyone else) tries to read USARTF0_DATA, it actually reads the Rx register.. so i think that’s normal, and there’s no need to worry.

      I am not sure if this option is available in the XMEGA (sorry i work with many MCUs..) but if you turn on the local loop back (tying Rx and Tx internally), you should be able to overcome this :)

      Hope this helps.

  • Sameen says:

    I am looking for ATxmega library for ORCAD..kindly help me out..

  • Leon says:

    Do not use hexadecimal values when writing to registers! You are not a robot, are you? Imagine you have 32-bit microcontroller instead of 8-bit. And what? 0x1F5B59AE or something is convenient? Find a bug in that code

  • Emilio Torres says:

    I am currently using an ATxmega32A4U. I was initially looking for a mcu with USB capabilities. The first thing that attracted me was the fact that this mcu is about the same price as the popular atmega328, and much cheaper than the megas with USB, which is hard to explain based on its superiority in almost every aspect.
    Xmegas are, indeed different beasts but the increased complexity and cool features require higher programming skills, specially if one intends to really take advantage from the DMA or the event system.
    I agree that specific information can be hard to find, not because the lack of documentation, but because its abundance.

  • Leonardo says:

    Hi, ASF is not easy to start but cut-down development time.

    I just started my new blog where I will talk about electronics including ASF (Atmel Software framework) with articles and examples.

    Blog is in Italian but also a computer-translated version is avaible with the right panel on website

    Leonardo

  • Ibrahim KAMAL says:

    Hello Mostafa,

    I am not teaching. If you search carefully, you’ll find that ATMEL has tones of documentations, applications notes, manuals..

    The XMEGA A3 manual alone is 445 pages! http://www.atmel.com/Images/doc8077.pdf

    This is how i migrated from atmega to xmega, and there is no reason you can’t :)

  • MOSTAFA says:

    HI

    i look for a xmega book but i dont find . can you a introduce me easy reference or a book for xmega just like your description in ikalogic site . iwant to migrate from atmega to xmega but xmega user manual in atmel site is very confused .

    are you teaching xmega

    thanks

Leave A Comment

Your email address will not be published. Required fields are marked *