Conditional compile for SPI

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm trying to make a driver for the xmega256 and m644 in ref. to SPI. The code below is in SPI.c, and their proto's. are in SPI.h, but it won't compile. What am i doin wrong?? MCU = xmega in makefile.

The error is for the spi.h -- " macro names must be identifiers "

thanks in advance

SPI.C

#ifdef ( atxmega256a3 )
   void   init_spiC( void )
   {
   
   PORTC_DIRSET = 0xBE;
   //PORTD_DIRCLR = 0x10;
   //PORTC.PIN0CTRL = 0x30;
   PORTC_OUTSET = 0x1E;  //PORTB |= (1<<4);

   SPIC_CTRL  = 0x50;   //Enable, mstr and  ...
   //SPIC_STATUS = 0x00;  //... Fclk/4 ( if Fclk = 2MHz )

   }

uint8_t   spiC_wrt( uint8_t b )
{

SPIC_DATA = b;
while( !spic_done );
return   SPIC_DATA;

}

#else 

void   init_spi( void )
{
   
// set_led;   //sets a bit ( bit 6 )
DDRB = 0xBC;
PORTB = 0x1E;  //PORTB |= (1<<4);
SPCR  = 0x50;   //Enable, mstr and  ...
SPSR = 0x01;  //... Fclk/32.
/*
   SPCR = 0x40;
   SPSR = 0x00;
   SPCR = 0x50;
   */
}

uint8_t   spi_wrt( uint8_t b )
{

SPDR = b;
while( !(SPSR & 0x80) );
return   SPDR;

}

#endif

SPI.h

#ifdef ( atxmega256a3 )
   void   init_spiC( void );
   

uint8_t   spiC_wrt( uint8_t b );


#else 

void   init_spi( void );

uint8_t   spi_wrt( uint8_t  );

#endif

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1. if you indent and lay out your code neatly it always works better.

2. it is easier to use the compiler supplied device macro device names. (avr-gcc would be: __ATxmega256a3__)

3. you appear to have a macro for SPIC.CTRL called 'SPIC_CTRL'

The simplest way to debug any of this sort of problem is to look at the pre-processor output. (avr-gcc -E)

Then you see what the compiler sees. The solution is normally obvious.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's because "(" is not a valid macro name. Get rid of the brackets in the #ifdef statement.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I prefer using the defined() operator rather than the shorthand #ifdef.

Quite often you have an extended conditional block. It lines up nicely.

#if   defined(__GNUC__)
#include 
...
#elif defined(__CODEVISIONAVR__)
#include 
...
#elif defined(__IAR_SYSTEMS_ICC__)
#define ENABLE_BIT_DEFINITIONS
#include 
#include 
#else
#error Compiler not defined
#endif

#ifdef is best used for a single conditional block.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're both right, it compiles -- Nice, real nice !!

Quote:
3. you appear to have a macro for SPIC.CTRL called 'SPIC_CTRL'

I can assign an xmega reg. value using syntax of '.' or '_' .

thanks alot !

jerome

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Spoke too soon ! It compiled when i used mega644 in MAKEFILE, but when i use the xmega I get 1 error in main.c "undefined ref. to init_spi", where it looks like this in main.c : init_spi();

spi.c is put in the makefile SRC.

SPI.c

#include   
#include 

#include "SPI.h"

#if defined ( _atxmega256a3_ )
   
   void   init_spi( void )
   {
   
   PORTC_DIRSET = 0xBE;
   //PORTD_DIRCLR = 0x10;
   //PORTC.PIN0CTRL = 0x30;
   PORTC_OUTSET = 0x1E;  //PORTB |= (1<<4);
   SPIC_CTRL  = 0x50;   //Enable, mstr and  ...
   //SPIC_STATUS = 0x00;  //... Fclk/4 ( if Fclk = 2MHz )

   }

uint8_t   spiC_wrt( uint8_t b )
{

SPIC_DATA = b;
while( !spic_done );
return   SPIC_DATA;

}

#elif  defined ( _atmega644_ ) 

void   init_spi( void )
{
   
DDRB = 0xBC;
PORTB = 0x10;  //PORTB |= (1<<4);
SPCR  = 0x5D;   //Enable, mstr and  ...
SPSR = 0x00;  //... Fclk/16.
DDRD = 0x0F;

}


void   spi_wrt( uint8_t b )
{

SPDR = b;
while( !(SPSR & 0x80) );
//return   SPDR;

}
#endif

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here are the compiler defined values for the MCU types for avr-gcc.
http://www.nongnu.org/avr-libc/u...

__AVR_ATxmega256A3__

I also like to use #error and #warning when testing #if/#else
so I know for sure what's being compiled when.

#if defined (foo)
#warning foo is defined
#elif defined (bar)
...
#else
#error How did I get here
#endif
Last Edited: Mon. Jan 25, 2010 - 07:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

init_spiC or init_spi :?:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It was init_spi() in main when i compiled w/ mega644. In latest spi.c code, it's init_spi for both; since I'm trying to make it generic. I'll use #error and reply if it turns up anything ( thanks for it -- I've never used conditionals ).

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Based on atomicdog's advice maybe try:

#include    
#include  

#include "SPI.h" 

#if defined (__AVR_ATxmega256A3__) 
    
   void   init_spi( void ) 
   { 
    
   PORTC_DIRSET = 0xBE; 
   //PORTD_DIRCLR = 0x10; 
   //PORTC.PIN0CTRL = 0x30; 
   PORTC_OUTSET = 0x1E;  //PORTB |= (1<<4); 
   SPIC_CTRL  = 0x50;   //Enable, mstr and  ... 
   //SPIC_STATUS = 0x00;  //... Fclk/4 ( if Fclk = 2MHz ) 

   } 

uint8_t   spiC_wrt( uint8_t b ) 
{ 

SPIC_DATA = b; 
while( !spic_done ); 
return   SPIC_DATA; 

} 

#elif  defined (__AVR_ATmega644__) 

void   init_spi( void ) 
{ 
    
DDRB = 0xBC; 
PORTB = 0x10;  //PORTB |= (1<<4); 
SPCR  = 0x5D;   //Enable, mstr and  ... 
SPSR = 0x00;  //... Fclk/16. 
DDRD = 0x0F; 

} 


void   spi_wrt( uint8_t b ) 
{ 

SPDR = b; 
while( !(SPSR & 0x80) ); 
//return   SPDR; 

} 
#endif 

BTW you have:

uint8_t   spiC_wrt( uint8_t b )
void   spi_wrt( uint8_t b )

surely they both have to have the same name and prototype or are you going to wrap all invocations conditionally too?

Also I WOULD do what you are doing in the 256A3 version and return a uint8_t as well as send one as SPI always involves both Tx and Rx even if one of them is ignored.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've been away for a few days, so I'm sorry for the late reply. Clawson, I didn't know that I would have to wrap each invocation conditionally ( I thought i could use different names because of the conditional block ). Now they both have the same name and my code is exactly what you have in your post. I've also included A.dog's
#warning for each MCU:

#warning "it's a xmega256A3"
.
.
.

#warning "it's a 644"

But I still get the same error msg. It compiles if i comment out init_spi; in main.c, but the appropiate #warning msg never prints under either case.

Obviously, it's not executing the conditional blk. at all, is there a std. header file i need to include to make it work ?

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

Last Edited: Wed. Feb 3, 2010 - 05:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can you show us the exact error and the whole compiler output?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A.dog, how do i copy the compile output?

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to first find the output window. Where it is depends on if your using AVRstudio or Programmers Notepad or ...

Highlight all the output with the mouse then do ctrl+c to copy.

it should look something close to this...

Quote:
avr-g++ -mmcu=atxmega128a1 -Wall -gdwarf-2 -std=gnu++0x -fno-implicit-templates -frepo -fno-threadsafe-statics -fno-exceptions -ffunction-sections -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fshort-enums -MD -MP -MT app.o -MF d

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I was r.clickin' but then copy wouldn't h.light, so thanks for that!!!

main.c

#include       
#include 

#include "SPI.h"

void   main(void)
{

//clr_rst;
_delay_ms(300);

init_spi();

}

Quote:
> > "make.exe" all

-------- begin --------
avr-gcc (WinAVR 20090313) 4.3.2
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Compiling C: main.c
avr-gcc -c -mmcu=atmega644 -I. -gdwarf-2 -DF_CPU=1000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./main.lst -std=gnu99 -MMD -MP -MF .dep/main.o.d main.c -o main.o
main.c:6: warning: return type of 'main' is not 'int'

Compiling C: SPI.c
avr-gcc -c -mmcu=atmega644 -I. -gdwarf-2 -DF_CPU=1000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./SPI.lst -std=gnu99 -MMD -MP -MF .dep/SPI.o.d SPI.c -o SPI.o

Linking: main.elf
avr-gcc -mmcu=atmega644 -I. -gdwarf-2 -DF_CPU=1000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o -std=gnu99 -MMD -MP -MF .dep/main.elf.d main.o SPI.o --output main.elf -Wl,-Map=main.map,--cref -lm
main.o: In function `main':
c:\winavr-20090313\projects\mega_644\128x64_lcd/main.c:19: undefined reference to `init_spi'
make.exe: *** [main.elf] Error 1

> Process Exit Code: 2
> Time Taken: 00:01

I use pn

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What does spi.c and spi.h look like?
Are you sure you have __AVR_ATmega644__ spelled right?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Are you sure you have __AVR_ATmega644__ spelled right?

All correctly spelled. SPI.c -- exactly as in Clawson's reply. Latest SPI.h is below.

SPI.h

void   init_spi( void );
uint8_t   spiC_wrt( uint8_t  );

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

indianajones11 wrote:
All correctly spelled.
Apparently not. And if it is really correctly spelled, then there must be some other problem. So show the content of that file.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is worthwhile to always use a default in a #if .. #elif .. block e.g. #else #error #endif.

Use

avr-nm -g SPI.o    # see one modules global symbols
avr-nm -gA *.o     # see all modules global symbols

If you pipe the latter command through egrep, you can narrow it down to the symbols you want.

Regarding debugging your conditional defines, either ask make to produce file.i or just pre-process and pipe through egrep.

You will probably find making 'file.i' is easier. You just load into the editor and inspect what the pre-processor has done.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I got it!! Very Bad: _AVR_ATmega644_

Very good: __AVR_ATmega644__ ( Beginning and ending underscores must be 2 lengths, NOT 1 ). I went to avr/io.h and copy / pasted m644 macro name .

Thanks all, peace out.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1