style question

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

hi
ive been seeing alot of signals or bit positions in this forum being used like
"(1<<signal_name)"
which to me looks like a bit shift. whats wrong with just #defining it like
"#define signal_name 0b00001000"
or something like that?
while we're semi on the subject can anyone recomend a good embedded c programming book? ive got a couple regular c books but i could use one that is more microcontroller oriented.

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

Occasionally, you really need a bit number instead of a bit mask,
that's why Atmel has probably chosen to declare all bits as bit values
instead of bit masks. This happens primarily in assembly instructions
like SBI, CBI, SBIS etc. but the header file defining the IO bits and
registers is suitable for assembly as well as C.

I agree with you, for C only, defining them as bit masks would have
been the better solution (and is in fact what you can see on most
other C applications that run close to the hardware, like operating
system drivers).

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

so basicaly anytime i want to flip bits in one of the SFRs i have to do it like
"SFR |= (1<<BIT_NAME); " or define my own bitmasks right? does the compiler evaluate the 1<<BIT_NAME and replace it with a number, or does it actualy generate assembly instructions for this?

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

> so basicaly anytime i want to flip bits in one of the SFRs i have to
> do it like "SFR |= (1<<BIT_NAME); " or define my own bitmasks right?

That's the portable way, yes.

avr-libc provides the macro _BV() for your convenience.

> does the compiler evaluate the 1<<BIT_NAME and replace it with a
> number

Sure, as soon as you've got optimization turned on. Basically any
compile-time constant expression will be replaced by a fixed number
then. The optimization goes even beyond that, if the compiler notices
the operands in question are suitable for an SBI or CBI instruction,
it will replace the read-modify-write cycle by these instructions.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

twidget2 wrote:
does the compiler evaluate the 1<<BIT_NAME and replace it with a number, or does it actualy generate assembly instructions for this?

A good way to figure out what the compiler does is to look at the list file generated when compiling. For instance, this output from the ImageCraft compiler:

(0128) 	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1);
    0056 E582      LDI	R24,0x52
    0057 BD8C      OUT	0x2C,R24
(0129) 
(0130) 	SPCR |= (1<<SPE)|(1<<MSTR);
    0058 B58C      IN	R24,0x2C
    0059 6580      ORI	R24,0x50
    005A BD8C      OUT	0x2C,R24
(0131)
(0132) 	SPCR &= ~(0<<SPE);
    005B B58C      IN	R24,0x2C
    005C 7F8F      ANDI	R24,0xFF
    005D BD8C      OUT	0x2C,R24

You can see the C code on line 128 generates a bit mask, the code on line 130 sets 2 bits, and the code on line 132 clears a bit.

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

Quote:
code on line 132 clears a bit

It actually does nothing. Line 132 resolves to
ANDI   R24,0xFF

Perhaps you ment

SPCR &= (0<<SPE); 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> Perhaps you ment
> Code:
> SPCR &= (0<<SPE);

Which would be an obfuscated way to say

SPCR = 0;

Guys, just drop that (0 << foo) stuff, it only obfuscates the code,
and serves no good purpose. You can shift a zero by whatever amount
of bits, it will remain a zero. If you want to clear a bit, it's
still you need a bit (thus a `one') first, before you can clear
anything:

SPCR &= ~(1 << SPE);

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

Of course I was wrong.

I wrote:

(0132)    SPCR &= ~(0<<SPE); 

When:

(0132)    SPCR &= ~(1<<SPE); 

should work.

Look at the output from the compiler:

(0127) SPCR &= (0<<SPE);
    0056 2422      CLR	R2
    0057 BC2C      OUT	0x2C,R2
(0128) 
(0129) SPCR &= ~(0<<SPE);
    0058 B58C      IN	R24,0x2C
    0059 7F8F      ANDI	R24,0xFF
    005A BD8C      OUT	0x2C,R24
(0130) 
(0131) SPCR &= ~(1<<SPE);
    005B B58C      IN	R24,0x2C
    005C 7B8F      ANDI	R24,0xBF
    005D BD8C      OUT	0x2C,R24

It looks like the correct way to clear a bit is this:

SPCR &= ~(1<<SPE);