// C Code Example char cSREG; cSREG = SREG; /* store SREG value */ /* disable interrupts during timed sequence */ _CLI(); EECR |= (1<<EEMPE); /* start EEPROM write */ EECR |= (1<<EEPE); SREG = cSREG; /* restore SREG value (I-bit) */
No doubt, the Atmel guys not only know their controller pretty well, their also
know about their compiler.
And they know: if the compiler detects that the operand has only one single bit set it will generate an
sbi instruction with the bit position of that bit.
sbi 0x1f, 2 ; set bit 2 in EECR sbi 0x1f, 1 ; set bit 1 in EECR(If they coded
EECR |= (1<<EEMPE) | (1<<EEPE);which gives the same result but looks much better at first glance the operand was "6" (binary 00000110) where more than one bit is set. So, instead of generating two
sbiinstructions this is what would be produced:
in r24, 0x1f ; EECR ori r24, 0x06 ; 6 = 4 + 2 out 0x1f, r24 ; EECRwhich takes one more instruction.)
Even if you declare constants like _EEMPE_ = 4 and _EEPE_ = 2, which are the results of (1<<EEMPE) and (1<<EEPE);
const byte _EEMPE_ = 4; const byte _EEPE_ = 2; ... EECR = EECR | _EEMPE_; EECR = EECR | _EEPE_;
If you don't believe just try
EECR |= ( (1<<EEMPE) | (1 << 9) | (9 >> 5) );(1 << 9) will clear all the bits in a byte, the same with (9 >> 5)
sbi 0x1f, 2 ; set bit 2 in EECR
So what really happens is
the compiler completely evaluates the operand just to find out there is only 1 bit set no matter if the source was
EECR |= (1 << EEMPE) or
EECR |= 4.
It determines that bit position and, surprisingly gets
the same result as the programmer coded: EEMPE.
If I were Atmel I had not defined the bit positions rather than the values
you get when that bit is set.
_BVmacro. As it is performed while preprocessing it does not help making your code faster.