A simple question: Why doesn't this get optimized to SBI/CLI

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

Hey everyone,

I'm just wondering why doesn't this get optimized to SBI/CLI, I've got -o3 set.

	TIMSK  |= (1 << OCIE1A);						// Enable CTC1A interrupt
00000050  IN R24,0x39		In from I/O location 
00000051  ORI R24,0x40		Logical OR with immediate 
00000052  OUT 0x39,R24		Out to I/O location 
			TCCR1B |= (1 << CS10);				// Start timer
0000006A  IN R18,0x2E		In from I/O location 
0000006B  ORI R18,0x01		Logical OR with immediate 
0000006C  OUT 0x2E,R18		Out to I/O location 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In the first one the location is 0x39, the second it's 0x2E - that's out of range for SBI which needs 0x00..0x1F. On the whole only PORT/PIN, TWI, ADC and UART registers are usually found in range of SBI/CBI

Which model of AVR by the way? I see, for example that mega16 has TCCR1B at 0x2E and TIMSK at 0x39. the 32 registers in range of SBI/CBI on that chip are: EEARH, EEARL, EEDR, EECR, PORTA, DDRA, PINA, PORTB, DDRB, PINB, PORTC, DDRC, PINC, PORTD, DDRD, PIND, SPDR, SPCR, SPSR, UDR, UCSRA, UCSRB, UBRRL, ACSR, ADMUX, ADCSRA, ADCH, ADCL, TWDR, TWAR, TWSR, TWBR

That does seem a shame - you'd never need fast bit access to something like UBRRL and yet some registers that could benefit like timer flasg are out of range.

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

It's an Attiny2313.

And thanks for clarifying.

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

See chapter 23 ("Register Summary") in the datasheet. SBI/CBI only work on 0x1F down (it's kind of a shame that 0x1F is "wasted"). At least al three GPIORn registers are in SBI/CBI range so you can use them for 24 fast acting bit variables.

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

In practice you seldom change the bits in TCCR1B.
You set them to YOUR_INITIAL_VALUE or stop with 0.

So you are unlikely to need |=.
Avr-gcc is likely to start your timer with a LDI, OUT.
It will probably just need a single OUT to stop the timer. (it always keeps a 0 in R1)

Occasionally you worry about cycles when stop/starting a timer.

David.

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

There is even more waste of the precious Bit-addressable locations in other devices like ATmega48/88/168

15 of the 32 bit-addressable loactions are "Reserved".

Registers like GPIOR1/2 that could be used to implement flags are *NOT* bit addressable and thus are useless.

avrfreaks does not support Opera. Profile inactive.

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

Quote:

15 of the 32 bit-addressable loactions are "Reserved".

Registers like GPIOR1/2 that could be used to implement flags are *NOT* bit addressable and thus are useless.


Yup GPIOR0 is the only really useful one in 48/88/168.

You'd have thought Atmel might have learned their lesson but I just started messing with Xmega's the other day and it turns out that of the 64 locations in reason of IN/OUT a while block of 16 are unsued, yet they could have provided more "VPORT"s to map PORT/PIN registers into there!

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

Quote:

There is even more waste of the precious Bit-addressable locations in other devices like ATmega48/88/168


Indeed--Atmel did us no favours on enforcing the "new and standardized Mega AVR I/O memory map" on that family, especially. IMO a number of adjectives could be used: stupid, short-sighted, lazy, insane, ... Why bother with I/O space at all?--go all the way to brain-dead (Tiny10) and eliminate it.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:
Indeed--Atmel did us no favours on enforcing the "new and standardized Mega AVR I/O memory map" on that family, especially. IMO a number of adjectives could be used: stupid, short-sighted, lazy, insane, ... Why bother with I/O space at all?--go all the way to brain-dead (Tiny10) and eliminate it.
My suspicion is that reserving a range of addresses exclusively for port io simplified their circuitry somehow.
If not, then it's just dumb.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

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

An optimizer would have to be very smart about using SBI/CBI since older AVRs use byte, not bit, SBI/CBI operations and mess things up on clearing bits in interrupt flag registers. The age/type of AVR combined with the specific register type would make SBI/CBI optimization dangerous for some AVRs, or at least allot more complicated to optimize correctly. This might have influenced the compiler optimizer design choices from the very beginning?

Last Edited: Sat. Mar 3, 2012 - 05:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please explain.

I thought that the basic AVR instruction set has been the same since AT90Sxxxx days.

Ok, avr-gcc uses different models for large-memory or no MUL etc families.

Which families implement SBI/CBI differently?
Or have different interrupt response behaviour?

David.

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

Quote:

Which families implement SBI/CBI differently?

Was it at about 48/88/168 where SBI/CBI stopped being a read-modify-write and became atomic?

An old mega16 datasheet has this:

Quote:
Do not use Read-Modify-Write instructions (SBI and CBI) to set or clear the MPCM bit. The MPCM bit shares the same I/O location as the TXC Flag and this might accidentally be cleared when using SBI or CBI instructions.

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

I don't unterstand what you mean with "use byte". It does not really matter how you write it down on the high language level.

#define PORTX (*((unsigned char volatile*) 0x2b))

void set (void)
{   
    PORTX |= 1 << 4;
    PORTX &= ~(1 << 7);
}

With avr-gcc 3.4. from 2006 I get

set:
	sbi 43-0x20,4
	cbi 43-0x20,7
	ret

With newer versions of avr-gcc the code is the same, but might be print differently like

set:
	sbi 0xb,4
	cbi 0xb,7
	ret

@admin: The forum view of this thread at "forum&f=2" got stuck somehow.

avrfreaks does not support Opera. Profile inactive.

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

A byte SBI/CBI operation will rewrite the current value of the entire 8 bit register back into the register with only one bit affected by the SBI/CBI. Think about what happens to an interrupt flag bit that SBI/CBI is not trying to change, but the interrupt flag bit is set, SBI/CBI will rewrite the one value back to this interrupt flag and clear it even though SBI/CBI never intended to clear this flag.

This is not a problem with the newer bit SBI/CBI operation where this interrupt flag would not be accidentally changed.

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

Why would anyone use |= to interrupt flags register?
This is why you always use = with TIFR.

Any SBI is inherently read-modify-write.
Using the |= C statement is specifically asking for a read-modify-write. If this has side-effects, you need to live with them. Or preferably use the correct statements in the first place.

David.

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

david.prentice wrote:
Any SBI is inherently read-modify-write.
I would add any old AVR SBI/CBI is inherently read-modify-write for the entire register byte. Newer AVRs are inherently write only for the register single bit.

*edit: Come to think of it, I could be wrong. I never tried to CBI a newer AVR interrupt flag bit that was already set to see if it correctly had no effect on the flag. If this actually cleared the set interrupt flag, then I would have to say newer AVRs SBI/CBI is inherently read-modify-write for only the register bit (it is just a read-modify-write would not make sense for a single bit, but I really do not know how it was done). Who would care anyway, there is no reason in this universe to CBI an AVR interrupt flag.

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

Quote:
I never tried to CBI a newer AVR interrupt flag bit that was already set to see if it correctly had no effect on the flag.
With a mega88 in simulator 2, it works correctly. I still have to try it on a real chip.

Regards,
Steve A.

The Board helps those that help themselves.

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

Even if it works, it's not the job of a compiler of generating CBI/SBI to clear a flag bit...

avrfreaks does not support Opera. Profile inactive.

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

Quote:

Please explain.

I thought that the basic AVR instruction set has been the same since AT90Sxxxx days.


David--

Pull up a datasheet from a real AVR, from the time when men were men, women were disgusted with that, and AVR model numbers began with "AT90S...". Take e.g. AT90S8535 as a base, and lay out the Register Summary alongside those of AT90S8515, AT90S4433, AT90S8515, and AT90S2313. You'll see the pattern of the "original" I/O register assignment convention. Note all the I/O was within IN/OUT range, and the SBI/CBI range is fairly well packed.

But the new millennium arrived, and to serve us better the gurus decided on the "new" Mega I/O layout. Print out the '48/'88 Register Summary and lay it aside e.g. AT90S4433. See how sparse the precious low I/O address space is? The only bone we were tossed was GPIOR0. Only 0, not 1&2.

Now look at the fairly sparse IN/OUT address space. Indeed all or nearly all of Mega88-family I/O could be put 0x5f and below. Using the "new standard" Mega I/O map >>does<< make a difference in code size, and the percentage is significant on a Mega48-class app.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

SprinterSB wrote:
Even if it works, it's not the job of a compiler of generating CBI/SBI to clear a flag bit...

??? Was this said in a haughty tone, with nose pointed skyward? Is this akin to "The grapes are sour, anyway."? That's the way it sounded to me. (I'm probably missing something. ;) )

As long as we are stepping back into history, I was stoned by the masses chanting "Non-standard! Non-Standard!" every time I posted a CodeVision fragment such as "PORTB.2 = 1;" which generated SBI.

The traditional GCC rites had macros for that that were promoted as the One True Solution. More recently the compiler began generating SBI for "PORTB |= (1<<PB2);". Many many times it has been said in these Forums "Use 'PORTB |= (1<<PB2);' as the compiler will make it the optimum SBI". So if it isn't the compiler's job to generate the optimum code sequence for a common construct, whose job is it?!?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Usually its the compilers job to create the best code. But due to side effekts this can be tricky with so IO registers - so for these registers full controll to the source code is not a bad solution.

Using an old AVR, CBI on an interrupt-flag register is funny: It clears all interrupt flags except the one you might want to.

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

Quote:
There is even more waste of the precious Bit-addressable locations in other devices like ATmega48/88/168

I think U2 beats MegaX8 with that.

From programmer's point of view AVRs have 0x60 registers(0x00 to 0x5F), with varying functionality/constraints.

    -mov/movw/in/out take 1 clock and allow copying. -sbr/cbr/Sbi/cbi/sex/clx take 1/2 clocks, modify bits, can access only the subsets of 0x60.
    -some registers can be the arguments for conditionals sbrs/sbrc/sbis/sbic/brbs/brbc.
    -etc

Swiss cheese, Mr. Atmel.

No RSTDISBL, no fun!

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

Note that in standard C,
there is no way to order the compiler to change a bit without a RMW on the containing byte.
Generating SBI and CBI instructions for code that assigns to volatile bytes is standard-conforming
only in cases where the compiler has enough information to apply the as-if rule.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

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

Quote:
You'll see the pattern of the "original" I/O register assignment convention.

I agree that the special function registers have been moved about.
Quote:
I thought that the basic AVR instruction set has been the same since AT90Sxxxx days.

I was referring to LDI, OUT, SUBI etc.

I must admit that the SFR moves make a real difference to cycle (and instruction) counts.

Occasionally this is significant for timing. The code size is only really relevant for a tiny2313 or mega48.

I am very fond of Swiss cheese. Gruyere especially, but this does not have holes!

David.

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

Quote:
I was referring to LDI, OUT, SUBI etc.
But how SBI and CBI function has changed. Originally they were implemented as a full RWM of the entire register. This is no longer the case.
Quote:
Even if it works, it's not the job of a compiler of generating CBI/SBI to clear a flag bit...
But avr-gcc will, in fact, generate an CBI/SBI when it can (or rather, the optimizer).

Regards,
Steve A.

The Board helps those that help themselves.

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

Quote:

Note that in standard C,
there is no way to order the compiler to change a bit without a RMW on the containing byte.
Generating SBI and CBI instructions for code that assigns to volatile bytes is standard-conforming
only in cases where the compiler has enough information to apply the as-if rule.

You purists can sniff loudly with nose high all you want. The point is that I, and others, are writing applications for small AVR microcontroller models. You've seen the hue and cry when -O0 generated fragments are posted, about how ugly they are.

I'll say that IMO it >>is<< the compiler's job to generate the best instruction sequences possible, within the rules. And we've seen nothing in this thread (unlike some of the byte-promoted-to-int situations) where the "rules" would be violated without an explicit override. My mind goes back to the mid-80s and the Compiler Wars for x88...

I had to go back and review the entire thread to see how my "summary" above applied. lol We know why IN/OUT was used in the original post--'cause it was out of range of SBI. Sprinter and others agree with me that Atmel did '48-family users no favours with the "new and improved" Mega AVR8 I/O memory map pattern.

then it comes to Sprinter's "not the compiler's job" mention. Still confusing to me. The various brands have devised approaches to handle I/O references in an efficient manner. Including GCC's apparent magic of knowing by the magnitude of the final address whether to I/O-map or memory-map.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

It seems to me that a C compiler should obey the semantics of the statements it translates. e.g.
|= implies Read-Modify-Write

If you require a special extension that operates on individual bits, then it should be specified with a special operator, pragma or whatever.

As far as I am aware, you can act safely on interrupt write-only flags using regular C statements. Or there is some other mechanism such as reading SPSR or UDR.

David.

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

theusch wrote:
Quote:

Note that in standard C,
there is no way to order the compiler to change a bit without a RMW on the containing byte.
Generating SBI and CBI instructions for code that assigns to volatile bytes is standard-conforming
only in cases where the compiler has enough information to apply the as-if rule.

You purists can sniff loudly with nose high all you want. The point is that I, and others, are writing applications for small AVR microcontroller models. You've seen the hue and cry when -O0 generated fragments are posted, about how ugly they are.
I'm not sure about your definition of a purist.
I happen to be a great believer in the as-if rule.
-O0 output can be pretty awful even by the most tolerant of standards,
e.g. using six registers for the same two-byte address.
Using SBI and CBI instructions for single-bit changes to PORT and DDR registers is allowed by the as-if rule.
For that matter, when it works, I have no objection to compiling
"PORTB^=changes;" the same as "PINB=changes;".
Again, the as-if rule applies.
On the other hand, what does one do about PINB|=0x10;"?
If the processor is an ATmega168, the specified byte-size RMW
will produce a different result from an SBI instruction.
The C is silly, but rather difficult to outlaw on a processor that allows writing to a PIN register.
Quote:
Sprinter and others agree with me that Atmel did '48-family users no favours with the "new and improved" Mega AVR8 I/O memory map pattern.
Agreed.
Simply adding a set of port registers would give sixteen fast bit variables,
eight of which could be toggled fast and atomically.
Connecting them to pins would not be necessary.

Also, it seems to me that there were some rather high noses when
other OPs complained about the retirement of the sbi and cbi macros.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

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

Quote:
Newer AVRs are inherently write only for the register single bit.
Really? They are still two cycles, which implies there is a RMW going on at the HW level to me! The compiler can create code that handles atomicity at the SW level, but it's pretty helpless to handle bad choices of bits-sharing-registers at the HW level. I'd sooner believe that Atmel had removed such bit-conflicts or changed the way interrupts are handled than actually made sbi/cbi actually work bitwise...

The xmega has the clr, set, and tgl registers that I would believe are atomic even at hardware level.

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

Quote:

Really? They are still two cycles, which implies there is a RMW going on at the HW level to me!

I lost you. I thought nothing can interrupt a currently executing intruction so for all practical purposes it is atomic. Am I wrong, or misunderstanding something?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

I am fast losing the plot!

I agree with westfw. The hardware is probably doing RMW since it is using 2 cycles.
Yes, the 2-cycle single instruction is atomic. So what?

The recent general drift is that some SFRs take more instructions / cycles to access. Due to their memory address.

Whether you use C or ASM, the appropriate statements / instructions work fine. e.g. TIFR0 = 5 or LDI Ry,5 ; OUT TIFR0,Ry

If Ry already contains the required 'value', clearing 2 interrupt flags only takes 1 cycle. Likewise PINx writes.

Any attempt to do a totally inappropriate |= on PINx or TIFRx is going to take more than one clock cycle.

David.

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

Quote:

I am fast losing the plot!

I agree with westfw. The hardware is probably doing RMW since it is using 2 cycles.
Yes, the 2-cycle single instruction is atomic. So what?


OK, I thought this was about RMW sequences, and the stuff they are working with, being vulnerable to other changes from other sources during the RMW. I am under the impression that while a RMW might be going on internally during a SBI/CBI instruction it is not vulnerable to other accesses "wedging in".

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Quote:

OK, I thought this was about RMW sequences, and the stuff they are working with, being vulnerable to other changes from other sources during the RMW. I am under the impression that while a RMW might be going on internally during a SBI/CBI instruction it is not vulnerable to other accesses "wedging in".

I guess we are all interpreting the "problem" in different ways then. Consider an interrupt flag register with 01000100 in it and you want to clear bit 2. So you SBI reg,2. But the SBI instruction does an RMW so it reads the current state which is 01000100, sets bit 2 (pointless as it's already set) then writes the 8 bits back. This ends up clearing bit 2 and bit 6. THAT surely is the problem of SBI doing an RMW? Nothing to do with atomicity at all, its the very fact that it reads 8 bits, changes one then writes 8 bits. An SBI that really does just change just 1 of 8 bits using direct logic gate writes would not show this.

My understanding is that around the 48/88/168 point in AVR development SBI (and CBI) were changed from just doing an 8bit RMW (OR/AND) operation to be the true 1 bit affecting opcode.

Or have I also misinterpreted what the "issue" is here?

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

There are were at least two plots:
Grousing about the sparsity of the SBI/CBI address range since atmega48s.
Arguing about what the compiler should do and should be allowed to do.
SBI/CBI timing is new.
On that subject:

 ; atmega168
 LDI R16, 0xFF ; all ones
 OUT DDRB, R16
 OUT PORTB, R1 ; all zeros
 SBI PORTB, 0
 OUT PORTB, R1
 

For how long will the positive pulse on B0 last?
Can one tell from documentation?
This one expects one cycle,
otherwise there would seem no need for two cycles.
What is not obvious to me is why CBI and SBI would take longer than BST or BLD.

Edit: make port D outputs

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

Last Edited: Mon. Mar 5, 2012 - 06:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your are being a little optimistic with your example.
You set up the whole PORTB as high-impedance input.

Then switch on a 30k pull-up with SBI.
Then remove it with OUT.

If your AVR is running at 20MHz with about 20pF on the PORTB.0 pin, the time-constant is 30k x 20p = 600ns.
The AVR clock cycle-time is 50ns.

What do you expect to see?

If you used push-pull output drive, you would easily achieve 10R x 20 p = 200ps risetime.

My output impedance and trace capacitance are rough guesses. But 200ps in a 50ns period would look pretty sharp to me.

David.

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

I tested an actual mega88 with the following code:

#include  

int main(void) 
{ 

	DDRB = 0xff;
	PORTB = 0x00;
	OCR0A = 0x40;
	OCR0B = 0x80;
	TCCR0B = 1;

	while ((TIFR0 & (1<<TOV0)) == 0);

	TIFR0 |= (1<<TOV0);
	//TIFR0 &= ~(1<<TOV0);

	asm("NOP");
	asm("NOP");

	PORTB = TIFR0;

	while(1);
} 

The result with the |= line is 0x06 (OCF0A and OCF0B set, TOV0 clear). The result with the &= line is 0x07 (all three flags set). So there is not RMW with these opcodes either bit-wise or byte-wise.

Quote:

This one expects one cycle,
otherwise there would seem no need for two cycles.
Actually, 1.5 cycles (or some other fraction) is also possible. It wholly depends on the implementation. However I agree that it would likely be 1 cycle (assuming that you really meant to make the pin an output, not an input).

Regards,
Steve A.

The Board helps those that help themselves.

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

The sensible C statement is :

   TIFR0 = (1<<TOV0);       // clear single bit
                            // result will be 0b00000110
   // if you choose to use this C statement :
   TIFR0 &= ~(1<<TOV0);
   // you would read 0b00000111
   // 0b00000111 & 0b11111110 => 0b00000110
   // so you should expect 0b00000001
   // i.e. clear OCF0 and OCF1 and leave TOV0

So it is quite clear that the byte-wise C statements result in bit-wise CBI and SBI.

OTOH, why would anyone in their right mind use SBI instead of OUT?
And why would anyone ever use &= for a SFR that only reacts to set bits?

David.

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

david.prentice wrote:
Your are being a little optimistic with your example.
You set up the whole PORTB as high-impedance input.
Oops.
I'd left my head in my other hat.
'Tis corrected now.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
 TIFR0 = (1<<TOV0);

I agree that this is the proper way to clear an interrupt flag, assuming that the entire register is interrupt flags. But if it is, say, the ADIF flag that you want to clear, this will not work and the |= method must be used. If the register contains more than one interrupt flag, but also has other bits that are not interrupt flags, then it can become more complex to ensure that only the flag you want cleared is cleared while still leaving all other bits the same. However, I do not believe that there are any AVRs that have this situation: it is either all bits in the register are interrupt flags, or only one bit is.

   // if you choose to use this C statement :
   TIFR0 &= ~(1<<TOV0);
   // you would read 0b00000111
   // 0b00000111 & 0b11111110 => 0b00000110
   // so you should expect 0b00000001
   // i.e. clear OCF0 and OCF1 and leave TOV0 

This might be the case. But as stated earlier, avr-gcc with optimization turned on will try to use SBI when it can (though it is certainly not guaranteed).

Regards,
Steve A.

The Board helps those that help themselves.