[TUT][C] Introduction to offsetof() via reading XMega SN

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This tutorial gives a very brief introduction to the obscure function offsetof() found in . Reading the XMega chip serial number, and XMega revision letter, is used as an example.

Quote:

offsetof() evaluates to the offset (in bytes) of a given member within a struct or union type, an expression of type size_t.

The offsetof() macro takes two parameters, the first being a structure name, and the second being the name of a member within the structure.

- http://en.wikipedia.org/wiki/Offsetof

Sounds rather uninteresting described that way, a more applicable article to us is "Learn a new trick with the offsetof() macro"
http://www.embedded.com/columns/technicalinsights/18312031?_requestid=402305, which gives some good examples of how to apply offsetof() to the usage of EEPROM access.

In a nut shell offsetof() tells you the number of bytes from the start of the structure, to an element of the structure. This allows your code to be portable across different CPU architectures, and keeps you from having to dig through obscure compiler documentation to find out how your given compiler will pack any given structure.

The following example offsetof() is used to locate the members of the structure XMega NVM_PROD_SIGNATURES_t structure:

/*
 * Example of using Offsetof() from stddef.h.
 *
 * This example reads the XMega chip serial number and revision.
 *
 * Who thought it was a good idea to put the revision letter on the
 * bottom of the chip?
 */


#include  /* uint8_t et.al */
#include  /* offsetof() */
#include 

/* From application note AVR1316: */
#include "avr_compiler.h" /* Compile with GCC release of WinAVR20090313 */
#include "sp_driver.h"

/* Change hex8() to match what your hardware needs to display a byte */
#define hex8(x) do{ /* display byte here */ }while(0)

int main( void )
{
  /* Read the part signature and revision: */
  hex8( MCU.DEVID0 ); hex8( MCU.DEVID1 ); hex8( MCU.DEVID2 );
  hex8( (uint8_t) (MCU.REVID+'A') );

  /* XMega serial number: */
  (void) SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, LOTNUM0 ) ); /* First read after reset or possibly Power Up returns zero, so read then toss this value */

  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, LOTNUM0 ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, LOTNUM1 ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, LOTNUM2 ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, LOTNUM3 ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, LOTNUM4 ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, LOTNUM5 ) ) );

  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, WAFNUM ) )  );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, COORDX0 ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, COORDX1 ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, COORDY0 ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, COORDY1 ) ) );

  /* Analog Calibrations: */
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, TEMPSENSE0 ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, TEMPSENSE1 ) ) );

  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, ADCACAL0 ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, ADCACAL1 ) ) );

  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, ADCBCAL0 ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, ADCBCAL1 ) ) );

  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, DACAOFFCAL ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, DACACAINCAL ) ) );

  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, DACBOFFCAL ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, DACBGAINCAL ) ) );

  /* Frequency Calibrations: */
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, RCOSC2M ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, RCOSC32K ) ) );
  hex8( SP_ReadCalibrationByte( offsetof( NVM_PROD_SIGNATURES_t, RCOSC32M ) ) );
}