Are bitwise operations unsafe?

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

I've find in some threads some posts saying that it's not good using many |= or &=, because registers are cleared in the way or something like that.

Can you elaborate a bit on this topic? I don't find anything about it.

Thanks

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

Do you have a specific problem or are you generally curious?
Have you read the tutorial on "Bit manipulation"?

Quote:
I've find in some threads some posts saying that it's not good using many |= or &=,

Point us to those threads, and preferrably to a formulation that you don't understand, and we can start discussing that.

No-one is going to write an essay for you on a subject that, as the question is posed, is quite wide.

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

When you are using C then (without checking the datasheet) it's not that easy to know. On a mega128 if I use:

PORTB |= (1<<PB5);

then that is atomic but if I use:

PORTF |= (1<<PF5);

that is not atomic. You can see this by studying the (optimised) code:

	PORTB |= (1<<PB5);
  ce:	c5 9a       	sbi	0x18, 5	; 24
	PORTF |= (1<<PF5);
  d0:	80 91 62 00 	lds	r24, 0x0062
  d4:	80 62       	ori	r24, 0x20	; 32
  d6:	80 93 62 00 	sts	0x0062, r24

The difference here is that PORTB has a RAM address of 0x38 while PORTF is at 0x62. SBI can only be used for (RAM) addresses between 0x20 and 0x3F (that is IO addresses between 0x00 and 0x1F). An SBI is atomic, a read-modify-write sequence is not.

BTW a strange fact is that PINF is in range of atomic instructions while PORTF is not.

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

Thank you, another thing I learn ;)

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

BTW atomicity is only important if a resource may be accessed within two or more threads of execution. POTF above may only be an issue if it is changed in both main()line code and an ISR(). You might want to move the actual port access code out of the ISR to avoid the need for atomicity protection.

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

You must understand what a shared resource means and all consequences it brings (resource shared between two or more contexts so that change made by one influences the other).

For example some data can be shared and accessed by both main and isr at the same time (from main context perspective). The problem rises when the access (like load+modify+store) of the former can be interrupted by the latter in between. If it is single opcode access (like movw), nothing wrong can happen, as an opcode cannot be interrupted in between.

But if you are trying for example to set bit0 in PORTx in main:

in main_temp,PORTx
ori main_temp,1<<0
out PORTx,main_temp

while ISR can interrupt it and write to bit1 of PORTx in between

in isr_temp,PORTx
ori isr_temp,1<<1
out PORTx,isr_temp

this will not bring anything good as the action of ISR can be canceled by main in this example.

in main_temp,PORTx
ori main_temp,1<<0
;ISR raised
in isr_temp,PORTx
ori isr_temp,1<<1
out PORTx,isr_temp
;reti
out PORTx,main_temp

Even more tricky case is when the other context is your hardware (a timer for example) or a task(with OS).

Quote:
BTW a strange fact is that PINF is in range of atomic instructions while PORTF is not.

It is because of sbix PINF,y . Neither DDRx, nor PORTx can be modified by hardware on m128 (unlike on newer devices) so there is no point using sbix with those as sbrx can be used.

No RSTDISBL, no fun!

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

We've strifed both bitwise manipulation and interrupts in general (and atomic acess in particular) in this thread. Here are three good tutorials:

Bit manipulation:
https://www.avrfreaks.net/index.p...

Newbies guide to interrupts:
https://www.avrfreaks.net/index.p...

Traps when using interrupts:
https://www.avrfreaks.net/index.p...

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

tigrezno wrote:
I've find in some threads some posts saying that it's not good using many |= or &=, because registers are cleared in the way or something like that.

Can you elaborate a bit on this topic? I don't find anything about it.

I suspect that this is a reference to interrupt flag registers.
Most interrupt flags are cleared by writing ones to them.
FLAGS|=anything will clear all the flags,
as will FLAGS=FLAGS.
There is a FAQ on the subject detailing what happens and why it's done that way.
The what part is correct.

Iluvatar is the better part of Valar.