Skip to content

Differences for the XMega implementation

Bob Frazier edited this page Dec 31, 2016 · 9 revisions

Differences for the XMega implementation

There are a few API changes that had to be made to support the XMega processors.


attachInterrupt

For the XMega, the attachInterrupt function is now defined as follows:

void attachInterrupt(uint8_t interruptNum, void (*)(void), int mode);

For C++ code, the 'mode' parameter gets a default value of 0.

Typical usage:

attachInterrupt(PORTD_INT0,              // the specific interrupt vector - see pins_arduino.h
                my_callback,             // user-defined callback function
                RISING                   // interrupt mode (can be LOW, HIGH, RISING, FALLING, CHANGE)
                | INT_MODE_PIN_DEFAULT   // the pin(s) to assign to this interrupt, or default pin 2
                | INT_MODE_PRI_DEFAULT); // interrupt priority, default is 'high' (optional)

The 'interruptNum' constants are in pins_arduino.h, typically defined similar to:

#define PORTD_INT0  0
#define PORTD_INT1  1
#define PORTC_INT0  2
#define PORTC_INT1  3
#define PORTE_INT0  4
#define PORTE_INT1  5
#define PORTA_INT0  6
#define PORTA_INT1  7
#define PORTB_INT0  8
#define PORTB_INT1  9
#define PORTR_INT0  10
#define PORTR_INT1  11

The constant 'EXTERNAL_NUM_INTERRUPTS' will equal the total number of available interrupts. Note that these constants vary from processor to processor. The E5 series only has 'INT0' interrupts, for example, and the A1(U) series has additional ports and interrupts.

The 'mode' parameter uses the following constants from 'Arduino.h':

#define INT_MODE_PRI_DEFAULT    0
#define INT_MODE_PRI_LOW   0x0040
#define INT_MODE_PRI_MED   0x0080
#define INT_MODE_PRI_HIGH  0x00c0
#define INT_MODE_PIN0      0x0100
#define INT_MODE_PIN1      0x0200
#define INT_MODE_PIN2      0x0400
#define INT_MODE_PIN3      0x0800
#define INT_MODE_PIN4      0x1000
#define INT_MODE_PIN5      0x2000
#define INT_MODE_PIN6      0x4000
#define INT_MODE_PIN7      0x8000
#define INT_MODE_PIN_DEFAULT    0

Multiple pins can be specified for interrupts. These are 'or'd with the following trigger types:

#define LOW  0x0
#define HIGH 0x1
#define CHANGE 2
#define FALLING 3
#define RISING 4

readCalibrationData

The 'readCalibrationData' function returns store calibration data. It is XMega-specific and necessary for features like the A:D converter.

The function is defined as:

uint8_t readCalibrationData(uint16_t iIndex);

where 'iIndex' is the index within the 'calibration data' that was stored during manufacturing.

Typical 'iIndex' values can be found in the appropriate avr 'io' header file. These need to be cast from 'const void *' to an unsigned short integer, as follows:

readCalibrationData((uint16_t)&PRODSIGNATURES_ADCACAL0);

For the ATXMega32E5, the 'product signatures' are defined as follows (from iox32e5.h):

/* NVM_PROD_SIGNATURES - Production Signatures */
#define PRODSIGNATURES_RCOSC8M  _SFR_MEM8(0x0000)
#define PRODSIGNATURES_RCOSC32K  _SFR_MEM8(0x0002)
#define PRODSIGNATURES_RCOSC32M  _SFR_MEM8(0x0003)
#define PRODSIGNATURES_RCOSC32MA  _SFR_MEM8(0x0004)
#define PRODSIGNATURES_LOTNUM0  _SFR_MEM8(0x0008)
#define PRODSIGNATURES_LOTNUM1  _SFR_MEM8(0x0009)
#define PRODSIGNATURES_LOTNUM2  _SFR_MEM8(0x000A)
#define PRODSIGNATURES_LOTNUM3  _SFR_MEM8(0x000B)
#define PRODSIGNATURES_LOTNUM4  _SFR_MEM8(0x000C)
#define PRODSIGNATURES_LOTNUM5  _SFR_MEM8(0x000D)
#define PRODSIGNATURES_WAFNUM  _SFR_MEM8(0x0010)
#define PRODSIGNATURES_COORDX0  _SFR_MEM8(0x0012)
#define PRODSIGNATURES_COORDX1  _SFR_MEM8(0x0013)
#define PRODSIGNATURES_COORDY0  _SFR_MEM8(0x0014)
#define PRODSIGNATURES_COORDY1  _SFR_MEM8(0x0015)
#define PRODSIGNATURES_ADCACAL0  _SFR_MEM8(0x0020)
#define PRODSIGNATURES_ADCACAL1  _SFR_MEM8(0x0021)
#define PRODSIGNATURES_ACACURRCAL  _SFR_MEM8(0x0028)
#define PRODSIGNATURES_TEMPSENSE0  _SFR_MEM8(0x002E)
#define PRODSIGNATURES_TEMPSENSE1  _SFR_MEM8(0x002F)
#define PRODSIGNATURES_DACA0OFFCAL  _SFR_MEM8(0x0030)
#define PRODSIGNATURES_DACA0GAINCAL  _SFR_MEM8(0x0031)
#define PRODSIGNATURES_DACA1OFFCAL  _SFR_MEM8(0x0034)
#define PRODSIGNATURES_DACA1GAINCAL  _SFR_MEM8(0x0035)

wait_for_interrupt

The 'wait_for_interrupt' function does what it says on the tin: It waits for an interrupt to occur, and after the ISR returns, it returns control to the calling function. This trick is performed by using one of the XMega's "sleep" modes, which can reduce overall current consumption.

It is implemented as:

void wait_for_interrupt(void);

low_power_delay

The 'low_power_delay' function is identical to the built-in 'delay' function, except that it makes use of one of the XMega's "sleep" modes, which can reduce overall current consumption.

It is implented as:

void low_power_delay(unsigned long ms);

where 'ms' is the number of milliseconds to delay. Since the system timer creates interrupts, there should be no deviation in actual performance between using 'delay' or 'low_power_delay' (other than the reduction in current consumption).