Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Warning: accessing bit variables are not atomic

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    www.mcselec.com Forum Index -> BASCOM-AVR Archive
View previous topic :: View next topic  
Author Message
Sarek

Bascom Member



Joined: 15 Oct 2009
Posts: 72

germany.gif
PostPosted: Tue Apr 29, 2014 4:04 pm    Post subject: Warning: accessing bit variables are not atomic Reply with quote

If you use bit variables in your program, the code generated by bascom compiler could cause strange problems.

the compiler reserves the space for bit variables at the same sram-byte.
This could cause problems with using bits in interrupts.

Code:

for example:

DIM mybit_mainloop As Bit
DIM ...... As Long  
DIM ...... As Long
DIM ...... As Long
DIM ...... As Long
DIM ...... As Long
DIM mybit_interrupt As Bit


Do
   ...
   ...
   ...
   Reset mybit_mainloop
   ...
   ...
Loop


Int_abc_isr:

   Set mybit_interrupt

Return


Int_xyz_isr:

   If mybit_interrupt = 1 Then
      Reset mybit_interrupt
      ...
      ... do something
   End If

Return

 


In this code above in interrupt Int_abc_isr there is bit set for the
second Interrupt Int_xyz_isr as Marker to do something.

If the mainloop was interrupted at the line:
Reset mybit_mainloop
it will happen that the bit => mybit_interrupt is reseted immediately when
the program goes back to main loop.

So bit variables should never be used in interrupts !!!
There could be a consistency problem because the compiler reserves SRAM at the same byte.

imho this could be a compiler bug

(BASCOM-AVR version : 2.0.7.7 )
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2335

blank.gif
PostPosted: Tue Apr 29, 2014 7:17 pm    Post subject: Re: Warning: accessing bit variables are not atomic Reply with quote

Sarek wrote:
imho this could be a compiler bug

Surprise, surprise - the bug is behind the screen Very Happy
It's a moot issue and well known.
Quote:
So bit variables should never be used in interrupts !!!

Any access, even to 8 bit variables, which is translated to more than a single opcode, for example any read/modify/write, must be made atomar in the main code, if also accessed by ISR code.
It's not the compiler's duty to take care of that.
Back to top
View user's profile
Neill

Bascom Member



Joined: 08 Dec 2008
Posts: 55

newzealand.gif
PostPosted: Thu May 01, 2014 6:04 am    Post subject: Reply with quote

I like to use bits, they can be very useful.

What I do is ensure that each bit has it's own RAM location like this:

DIM tick as bit
DIM dummy_tick_1 as bit
DIM dummy_tick_2 as bit
DIM dummy_tick_3 as bit
DIM dummy_tick_4 as bit
DIM dummy_tick_5 as bit
DIM dummy_tick_6 as bit
DIM dummy_tick_7 as bit

Yes it's clumsy but for me it's the easiest way around the issue.

You can use the Show Result feature in the IDE to check where the bits are stored.
Back to top
View user's profile
StefanHamburg

Bascom Member



Joined: 02 Mar 2008
Posts: 73
Location: Germany

blank.gif
PostPosted: Thu May 01, 2014 11:32 am    Post subject: Reply with quote

Then you also could use Byte-Variables.
Code:
DIM tick as Byte

But this is a matter of storage while the threadowners concern was related to timing and writing to variables from different code segments.
Back to top
View user's profile
Evert :-)

Bascom Expert



Joined: 18 Feb 2005
Posts: 2165

netherlands.gif
PostPosted: Thu May 01, 2014 8:37 pm    Post subject: Reply with quote

StefanHamburg wrote:
Then you also could use Byte-Variables.
Code:
DIM tick as Byte


It's also faster then using a bit
Code:

Dim Mybit as bit
Dim Mybytebit as  Byte

Mybit=1        'Takes 5 cycles
Mybytebit =1   'Takes 3 cycles

 

_________________
www.evertdekker.com Bascom code vault
Back to top
View user's profile Visit poster's website
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Thu May 01, 2014 11:31 pm    Post subject: Reply with quote

"It's also faster then using a bit "

I found that it used less flash when working with the matrix clock where I had to get as much out of the Mega8 as I could

Regards Paul
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 6197
Location: Holland

blank.gif
PostPosted: Fri May 02, 2014 9:23 pm    Post subject: Reply with quote

there is no single instruction that can alter a bit of a variable. so a read/write instruction on any memory location is not atomic by default. it is not a bug.
the same thing applies to bytes, ints, etc.
the alternative would be to disable interrupts before writing to a variable used in an ISR and enable it afterwards. I could add such an option. But then one looses control on where/when interrupts are enabled/disabled.
And since the compiler can not know if interrupts are active at that stage, extra code is need to be used instead of a simple cli/sei. sreg need to be read to know the I status and must only be enabled when it was active otherwise interrupts would be enabled even when they were not active.
But TS is right that for bits a warning is important since it is not obvious that these bits are shared in one byte. i will think about a good solution.

_________________
Mark
Back to top
View user's profile Visit poster's website
Arera

Bascom Member



Joined: 23 Sep 2007
Posts: 386
Location: Wuppertal, Germany

germany.gif
PostPosted: Tue May 06, 2014 12:20 pm    Post subject: Reply with quote

I'm confused, and I do not understand a thing.....
I may not use bit-vars in ISRs? I may not change any vars in ISRr.
I have to care to make vars atomic???? What does that mean? I read the interrupt chapter of the help again, but all I understand is, when using SAVEALL I don't need to worry about a thing.
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 6197
Location: Holland

blank.gif
PostPosted: Tue May 06, 2014 1:09 pm    Post subject: Reply with quote

when you update a byte to say 1 there is code like :
ldi r24,1
sts {b},r24

when there is an ISR it will save R24.
and restores it when done.
So no problem.

When we write a word like w=1
there is code like :
ldi r26, &H2 ; address of w &H302
ldi r27,&H3
ldi r24,1 ; value for w
ldi r25,0
st x+,r24 ; write to address
st x,r25

in this case an interrupt will save/restore everything as well, and even the fact that an ISR can interrupt at all times, it will not matter since all regs are saved as restored.
But of course when the ISR runs and it also writes to W, it will set W to a new value. And that value you loose when the code above continues. So you need to make sure yourself if this is possible. and how it should be handled. while the compiler could disable interrupts when writing to a variables in the main code and enable them afterwards, it might be the case the interrupt does not run at all times. that is why it is the programmers task to make the proper logic. It is the same as using the UART in the main code and the iSR. What happens if you print "ABCDEFG" in the main and "123" in the ISR? most likely it will not give the desired result.
But only the programmer can decide how it should work.



but a bit is stored in a byte. this means that when you have bit0 and say bit1 they are stored in the byte space BYTE.
Now to alter a bit one must load the data, alter the bit and write the data back.
example :
lds r24,{BYTE}
sbr r24,1 ; set bit 0
sts {byte},r24

but now when the ISR want to write to bit1 it has similar code :

lds r24,{BYTE}
sbr r24,2 ; set bit 1
sts {byte},r24

and if the ISR executes just after the register is loaded (lds r24,{BYTE} )
it will save r24 with value of r24 , say 0.
then it will set the value of the byte to 2 , restores r24 and returns. but r24 was 0 !
so setting bit0 will work but the change of bit1 is lost.

the alternative is to use a byte instead of a bit.
or to disable interrupts when writing to the bit in the main code.
So in practical way, only a bit can give a problem.

_________________
Mark
Back to top
View user's profile Visit poster's website
EDC

Bascom Expert



Joined: 26 Mar 2014
Posts: 1135

poland.gif
PostPosted: Tue May 06, 2014 2:52 pm    Post subject: Reply with quote

Another summary I read yesterday on forum here
http://mcselec.com/index2.php?option=com_forum&Itemid=59&page=viewtopic&t=11861&highlight=ds1821&sid=b7e80640645a6591e894ba93a235b417

I must read some instruction how link post Very Happy
Back to top
View user's profile Visit poster's website
kema

Bascom Member



Joined: 20 Sep 2004
Posts: 5
Location: Sweden

blank.gif
PostPosted: Tue Jun 17, 2014 1:30 pm    Post subject: Reply with quote

Hi!

I had a similar problem or actually the problem has been around for 1,5 years and triggered 3 times in total among 25 delivered units. So I would say it is hard to find!

Mark Alberts answered very good, as he would knowing everything about BASCOM, and as he states the danger lies in using bit variables both in interrupt routines and in the main loop as they might share the same byte address.

In the documentation there is no mentioning of this problem, in fact in the segmen "ON INTERRUPT" we are actually encouraged to use "simple flags" and in my world this is bit variables, so maybe this would be a good place to enter a warning text to make sure the bit variables you use inside interrupt routines are not in the same byte as the ones you use in your main loop.
I came to the same conclusion in a workaround as Neill to dimension dummy bits to fill up a byte and then to verify this with the compiler reports memory map of the variables.

I would class this as a compiler bug, due to the fact that it is not documented at all in the manual, and the only way to find it out is by dissassemble the code and make a time consuming deep analysis.
But I would fully accept that the bug fix for this is to add information about this in the documentation in the section "ON INTERRUPT", Memory Usage, Language fundamentals and Newbie problems or a new section describing hard-to-find problems.

On a side note to MWS: saying
"Surprise, surprise - the bug is behind the screen
It's a moot issue and well known."

Its OK coming from you, especially since you did add a smile, but I beg to differ on the ground stated above that it is not documented.

Apart for this small bug(?) I haven't had much problems with BASCOM for the last couple of years, but this one tooko more than a few hours to find.

Best regards, Kent

_________________
Kent Andersson
Back to top
View user's profile
MikeCraven

Bascom Member



Joined: 15 Aug 2009
Posts: 3

usa.gif
PostPosted: Mon Aug 18, 2014 5:37 am    Post subject: Bit Variables Reply with quote

Has anyone considered / tried using bit variables in the General Purpose I/O registers? GPIOR0 for example.

It appears that the assembler directives SBI and CBI can be used to set and reset only one bit with only one processor instruction using 2 cycles. In most cases it appears that the General Purpose registers are within the range of the SBI type instructions.

The normal If / Then instructions can be used to test the bit condition if the name is aliased in the variable definitions. MyVariable Alias GPIOR0.0 - and then - If MyVariable = 1 Then Something - will work. But you cannot use SBI MyVariable,0 to set or reset, you have to write SBI GPIOR0,0 to set a bit.

This should / would prevent an interrupt from corrupting a bit variable write.
Also, since these instructions (and the corresponding test instructions SBIC & SBIS) do not affect the status register or use any registers you can do simple things in the interrupt routine with the NoSave option set. And is much faster.

I realize this mixes assembly into the code, but might be useful. I have tried this in a simple program and it seems to work.
Any comments?
Mike
Back to top
View user's profile
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    www.mcselec.com Forum Index -> BASCOM-AVR Archive All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum