Static var reset in function: why?

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

Hi,
I use ATtiny13. I compile with -O0.
in var.h I have defined:
static unsigned char GlobalVar;
and I have make a func:
void MyCrazyFunc(void)
{
....
GlobalVar = 10;
}
In main:
{
GlobalVar = 5;
MyCrazyFunc();
//here my GlobalVar is 5!!! :shock:
}
Then my GlobalVar is equal after call function ?!!
My function run fine if I remove "static" declaration in:
static unsigned char GlobalVar;
Why???
Thanks

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

Rename your function to something other than MyCrazyFunc. The compiler is making judgements about your state of mind.

Seriously, use grep for GlobalVar. I would guess that you have a scope issue.

David.

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

Here's something that I think(!) is functionally equivalent to what you are saying:

#include "avr/io.h" 

static unsigned char GlobalVar;

void MyCrazyFunc(void) 
{ 
	GlobalVar = 10; 
} 

int main(void)
{ 
	GlobalVar = 5; 
	MyCrazyFunc(); 
	//here my GlobalVar is 5!!!  
	PORTB = GlobalVar;
	while(1);
}

and this produces:

0000006c :

static unsigned char GlobalVar;

void MyCrazyFunc(void) 
{ 
  6c:	8a e0       	ldi	r24, 0x0A	; 10
  6e:	80 93 00 01 	sts	0x0100, r24
  72:	08 95       	ret

00000074 
: GlobalVar = 10; } int main(void) { 74: 8a e0 ldi r24, 0x0A ; 10 76: 80 93 00 01 sts 0x0100, r24 GlobalVar = 5; MyCrazyFunc(); //here my GlobalVar is 5!!! PORTB = GlobalVar; 7a: 85 b9 out 0x05, r24 ; 5 7c: ff cf rjmp .-2 ; 0x7c

So PORTB get's set to 10 which is EXACTLY what you'd expect from this program. How does your example differ?

Cliff

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

Cliff,

Did you receive a coconut for posting #10000 ?

David.

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

David,

There was just a small shift in the space-time continuum and then I found myself in this ID instead!

Cliff

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

Does STATIC make it volatile???

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

No static makes it static. You need to use volatile to make it volatile. ;-)

BTW, it's effectively volatile because of the -O0 anyway which reminds me that my code above was built -Os (like all sensible code) and not -O0, this is what -O0 produces:

0000006c :

static unsigned char GlobalVar;

void MyCrazyFunc(void) 
{ 
  6c:	cf 93       	push	r28
  6e:	df 93       	push	r29
  70:	cd b7       	in	r28, 0x3d	; 61
  72:	de b7       	in	r29, 0x3e	; 62
	GlobalVar = 10; 
  74:	8a e0       	ldi	r24, 0x0A	; 10
  76:	80 93 00 01 	sts	0x0100, r24
  7a:	df 91       	pop	r29
  7c:	cf 91       	pop	r28
  7e:	08 95       	ret

00000080 
: } int main(void) { 80: cf 93 push r28 82: df 93 push r29 84: cd b7 in r28, 0x3d ; 61 86: de b7 in r29, 0x3e ; 62 GlobalVar = 5; 88: 85 e0 ldi r24, 0x05 ; 5 8a: 80 93 00 01 sts 0x0100, r24 MyCrazyFunc(); 8e: ee df rcall .-36 ; 0x6c //here my GlobalVar is 5!!! PORTB = GlobalVar; 90: e5 e2 ldi r30, 0x25 ; 37 92: f0 e0 ldi r31, 0x00 ; 0 94: 80 91 00 01 lds r24, 0x0100 98: 80 83 st Z, r24 while(1); 9a: ff cf rjmp .-2 ; 0x9a

But PORTB still ends up getting 10 (even if you go via this long route!)

BTW when built -Os, from the entry to main until the while(1) RJMP the code executes 4 machine cycles. When built -O0 it executes THIRTY-SIX machine cycles to achieve the same result. Is there REALLY an argument for using -O0?

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

WrightFlyer wrote:
Is there REALLY an argument for using -O0?

There is a separate thread about it, you participated in it! Yes, there is an argument for using -O0.

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

No there isn't. (IMHO ;) )

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

Quote:
in var.h I have defined:
static unsigned char GlobalVar;

Your problem probably stems from the fact that you are defining a variable in a .h file. You should never do this (unless you really know what you are doing).

Are MyCrazyFunc and main defined in the same file or separate files?

Regards,
Steve A.

The Board helps those that help themselves.

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

Thanks all people! :D
My vars are declare in separate file: var.h

MyCrazyFunc is example :oops:

Really function is:
void ResetId(void)
{
switch(GlobalVar){
case 1: Id = 0x08;
break;
case 2: Id = 0x09;
break;
case 5: Id = 0x0A;
break;
}
OtherGlobalVar = GlobalVar;
}
When I return from ResetId the var OtherGlobalVar is alwais '0'. but if I declare GlobalVar NOT static ,this work fine!
Thanks again!

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

OK, there's clearly something you are not telling us here. Would you agree, for example, that the following represents the "problem" you have:

#include 

static unsigned char GlobalVar; 
static unsigned char OtherGlobalVar; 
static unsigned char Id; 

void ResetId(void) 
{ 
	switch(GlobalVar){ 
	case 1: Id = 0x08; 
		break; 
	case 2: Id = 0x09; 
		break; 
	case 5: Id = 0x0A; 
		break; 
	} 
	OtherGlobalVar = GlobalVar; 
} 

int main(void){
	GlobalVar = 2;
	ResetId();
	PORTB = OtherGlobalVar;
	while(1);
}

OK, so when built this becomes:

00000092 :
static unsigned char OtherGlobalVar; 
static unsigned char Id; 

void ResetId(void) 
{ 
  92:	cf 93       	push	r28
  94:	df 93       	push	r29
  96:	cd b7       	in	r28, 0x3d	; 61
  98:	de b7       	in	r29, 0x3e	; 62
  9a:	22 97       	sbiw	r28, 0x02	; 2
  9c:	0f b6       	in	r0, 0x3f	; 63
  9e:	f8 94       	cli
  a0:	de bf       	out	0x3e, r29	; 62
  a2:	0f be       	out	0x3f, r0	; 63
  a4:	cd bf       	out	0x3d, r28	; 61
	switch(GlobalVar){ 
  a6:	80 91 60 00 	lds	r24, 0x0060
  aa:	28 2f       	mov	r18, r24
  ac:	33 27       	eor	r19, r19
  ae:	3a 83       	std	Y+2, r19	; 0x02
  b0:	29 83       	std	Y+1, r18	; 0x01
  b2:	89 81       	ldd	r24, Y+1	; 0x01
  b4:	9a 81       	ldd	r25, Y+2	; 0x02
  b6:	82 30       	cpi	r24, 0x02	; 2
  b8:	91 05       	cpc	r25, r1
  ba:	79 f0       	breq	.+30     	; 0xda 
  bc:	29 81       	ldd	r18, Y+1	; 0x01
  be:	3a 81       	ldd	r19, Y+2	; 0x02
  c0:	25 30       	cpi	r18, 0x05	; 5
  c2:	31 05       	cpc	r19, r1
  c4:	71 f0       	breq	.+28     	; 0xe2 
  c6:	89 81       	ldd	r24, Y+1	; 0x01
  c8:	9a 81       	ldd	r25, Y+2	; 0x02
  ca:	81 30       	cpi	r24, 0x01	; 1
  cc:	91 05       	cpc	r25, r1
  ce:	09 f0       	breq	.+2      	; 0xd2 
  d0:	0b c0       	rjmp	.+22     	; 0xe8 
	case 1: Id = 0x08; 
  d2:	88 e0       	ldi	r24, 0x08	; 8
  d4:	80 93 62 00 	sts	0x0062, r24
		break; 
  d8:	07 c0       	rjmp	.+14     	; 0xe8 
	case 2: Id = 0x09; 
  da:	89 e0       	ldi	r24, 0x09	; 9
  dc:	80 93 62 00 	sts	0x0062, r24
		break; 
  e0:	03 c0       	rjmp	.+6      	; 0xe8 
	case 5: Id = 0x0A; 
  e2:	8a e0       	ldi	r24, 0x0A	; 10
  e4:	80 93 62 00 	sts	0x0062, r24
		break; 
	} 
	OtherGlobalVar = GlobalVar; 
  e8:	80 91 60 00 	lds	r24, 0x0060
  ec:	80 93 61 00 	sts	0x0061, r24
  f0:	22 96       	adiw	r28, 0x02	; 2
  f2:	0f b6       	in	r0, 0x3f	; 63
  f4:	f8 94       	cli
  f6:	de bf       	out	0x3e, r29	; 62
  f8:	0f be       	out	0x3f, r0	; 63
  fa:	cd bf       	out	0x3d, r28	; 61
  fc:	df 91       	pop	r29
  fe:	cf 91       	pop	r28
 100:	08 95       	ret

00000102 
: } int main(void){ 102: cf 93 push r28 104: df 93 push r29 106: cd b7 in r28, 0x3d ; 61 108: de b7 in r29, 0x3e ; 62 GlobalVar = 2; 10a: 82 e0 ldi r24, 0x02 ; 2 10c: 80 93 60 00 sts 0x0060, r24 ResetId(); 110: c0 df rcall .-128 ; 0x92 PORTB = OtherGlobalVar; 112: e8 e3 ldi r30, 0x38 ; 56 114: f0 e0 ldi r31, 0x00 ; 0 116: 80 91 61 00 lds r24, 0x0061 11a: 80 83 st Z, r24 while(1); 11c: ff cf rjmp .-2 ; 0x11c

And when single stepped in the simulator the st Z,r24 at 0x011a results in 2 being output to PORTB. This is exactly what's been coded here.

So can you describe how your implementation differs from this?

By the way as further proof of the avoidance of -O0 argument that same code built -Os produces:

00000092 :
static unsigned char OtherGlobalVar; 
static unsigned char Id; 

void ResetId(void) 
{ 
  92:	90 91 60 00 	lds	r25, 0x0060
  96:	92 30       	cpi	r25, 0x02	; 2
  98:	31 f0       	breq	.+12     	; 0xa6 
	switch(GlobalVar){ 
  9a:	95 30       	cpi	r25, 0x05	; 5
  9c:	31 f0       	breq	.+12     	; 0xaa 
  9e:	91 30       	cpi	r25, 0x01	; 1
  a0:	39 f4       	brne	.+14     	; 0xb0 
	case 1: Id = 0x08; 
  a2:	88 e0       	ldi	r24, 0x08	; 8
  a4:	03 c0       	rjmp	.+6      	; 0xac 
		break; 
	case 2: Id = 0x09; 
  a6:	89 e0       	ldi	r24, 0x09	; 9
  a8:	01 c0       	rjmp	.+2      	; 0xac 
		break; 
	case 5: Id = 0x0A; 
  aa:	8a e0       	ldi	r24, 0x0A	; 10
  ac:	80 93 62 00 	sts	0x0062, r24
		break; 
	} 
	OtherGlobalVar = GlobalVar; 
  b0:	90 93 61 00 	sts	0x0061, r25
  b4:	08 95       	ret

000000b6 
: } int main(void){ b6: 82 e0 ldi r24, 0x02 ; 2 b8: 80 93 60 00 sts 0x0060, r24 GlobalVar = 2; ResetId(); bc: ea df rcall .-44 ; 0x92 PORTB = OtherGlobalVar; be: 80 91 61 00 lds r24, 0x0061 c2: 88 bb out 0x18, r24 ; 24 c4: ff cf rjmp .-2 ; 0xc4

(I know which I'd prefer!)

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

I could be wrong, but...

If his global variable is in another file (var.h), and is declared static, where would that variable be scoped? In all files that include var.h?

(I think I may be off the mark on this, though)

(long live the land of Os)

edit-

Forget it, it works fine for me with a static variable declared in a var.h file.

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

Curt,

Well static used on a global variable just affects it's scope. It's never a good idea to define variables in .h files (just declare them extern there and define them in ONE of the .c files) but even if var.h were included in two different .c files then all that's going to happen is that in both the compiler will treat the variable(s) as if it cannot be seen from beyond this single file that's currently being compiled.

However the fact that these variables are in .h and that's #include'd in the main.c should make no difference to whether it's done like that or they are defined directly in the .c file. After all #include is just a pre-processor text substitution process.

Last Edited: Thu. Oct 4, 2007 - 11:35 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> If his global variable is in another file (var.h), and
> is declared static, where would that variable be scoped?
> In all files that include var.h?

In *each* file that includes var.h, and each of these (called a
"translation unit") would instantiate a separate, distinct variable
for it.

Btw., technically, it's not even a global variable at all, because
its scope is the translation unit.

Jörg Wunsch

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

Last Edited: Thu. Oct 4, 2007 - 10:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The OP has never really explained his system.

main.c:
#include "var.h" // declare static globalvar
// call crazyfunction();

file2.c:
#include "var.h" // declare static globalvar
// define crazyfunction();

the statics are two independent variables, because we have two different scopes.

if the OP has only a single file, then the scope of his static will be the whole file. He should expect his code to work.

If he needs to use "Data hiding" in his crazyfunction he would be better off with keeping his static in that module and returning its value via his crazyfunction.

David.

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

his 'problem' can be reproduced-

main.c

#include "var.h"
int main(void){
    GlobalVar = 5;
    MyCrazyFunc();
    //here my GlobalVar is 5!!! Shocked
    return 0;
} 

functions.c

#include "var.h"
void MyCrazyFunc(void){
    GlobalVar = 10;
}
 

var.h

static unsigned char GlobalVar;
void MyCrazyFunc(void);

The lss listing will show that 2 different variable locations are being used for the 'single' global variable. Remove the 'static', now the same location is used for the global variable.

So, I assume he must be using a separate 'function' c file.