strange variable declaration problem...

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

I've got a very strange problem that I'm having trouble tracking down.
Basically, I have a block of code in an if statement. Inside the if statement, I declare a local temporary variable, which is a typedef called svc_t. I've removed any other reference to the variable, so all that happens is that the variable is declared in the if statement (and an unrelated flag gets cleared, which is why the if does not get optimized away by the compiler)

The problem is, with that variable declared, wierd stuff happens, namely, the rest of my program doesn't work. If I remove the declaration, everything works fine.

// check for received gateway messages from the uplink (rf/serial)

	uint8_t ul_flags = ul_u8_get_flags();

	// if a message is received:	
	if((ul_flags & _BV(ul_ReceivedGatewayMsg)) != 0){
		
		svc_t temp_reply; // *** code works with this commented out
		
		switch(gate_ul_msg.Service){
.... etc etc

This is what the compiler generates with the variable declared:
Note that some of this code is related to code that I omitted above.

33e:	cf 93       	push	r28
     340:	df 93       	push	r29
     342:	cd b7       	in	r28, 0x3d	; 61
     344:	de b7       	in	r29, 0x3e	; 62
     346:	2c 97       	sbiw	r28, 0x0c	; 12
     348:	0f b6       	in	r0, 0x3f	; 63
     34a:	f8 94       	cli
     34c:	de bf       	out	0x3e, r29	; 62
     34e:	0f be       	out	0x3f, r0	; 63
     350:	cd bf       	out	0x3d, r28	; 61
     352:	0e 94 f7 08 	call	0x11ee
     356:	0e 94 19 0a 	call	0x1432
     35a:	0e 94 a8 0a 	call	0x1550
     35e:	80 ff       	sbrs	r24, 0
     360:	09 c0       	rjmp	.+18     	; 0x374
     362:	80 91 eb 02 	lds	r24, 0x02EB
     366:	8e 31       	cpi	r24, 0x1E	; 30
     368:	11 f4       	brne	.+4      	; 0x36e
     36a:	0e 94 74 01 	call	0x2e8
     36e:	80 e0       	ldi	r24, 0x00	; 0
     370:	0e 94 ac 0a 	call	0x1558
     374:	0e 94 82 09 	call	0x1304
     378:	80 ff       	sbrs	r24, 0
     37a:	03 c0       	rjmp	.+6      	; 0x382
     37c:	80 e0       	ldi	r24, 0x00	; 0
     37e:	0e 94 86 09 	call	0x130c
     382:	2c 96       	adiw	r28, 0x0c	; 12
     384:	0f b6       	in	r0, 0x3f	; 63
     386:	f8 94       	cli
     388:	de bf       	out	0x3e, r29	; 62
     38a:	0f be       	out	0x3f, r0	; 63
     38c:	cd bf       	out	0x3d, r28	; 61
     38e:	df 91       	pop	r29
     390:	cf 91       	pop	r28
     392:	08 95       	ret

Here is what it looks like with the declaration removed:

 33e:	0e 94 e6 08 	call	0x11cc
     342:	0e 94 08 0a 	call	0x1410
     346:	0e 94 97 0a 	call	0x152e
     34a:	80 ff       	sbrs	r24, 0
     34c:	09 c0       	rjmp	.+18     	; 0x360
     34e:	80 91 eb 02 	lds	r24, 0x02EB
     352:	8e 31       	cpi	r24, 0x1E	; 30
     354:	11 f4       	brne	.+4      	; 0x35a
     356:	0e 94 74 01 	call	0x2e8
     35a:	80 e0       	ldi	r24, 0x00	; 0
     35c:	0e 94 9b 0a 	call	0x1536
     360:	0e 94 71 09 	call	0x12e2
     364:	80 ff       	sbrs	r24, 0
     366:	03 c0       	rjmp	.+6      	; 0x36e
     368:	80 e0       	ldi	r24, 0x00	; 0
     36a:	0e 94 75 09 	call	0x12ea
     36e:	08 95       	ret
     370:	08 95       	ret

There's quite a bit of difference. Note that some of the code (namely the call's) pertain to other code in that function which I chose to omit for readability. What is most confusing are the two cli's in the declared version. Why would declaring a temp variable cause the compiler to disable interrupts twice without re-enabling them, or disabling them at all for that matter?

I've also tried an array of uint8_t instead of my typedef, same problem. Other portions of my program have similar sections of code that work fine with temp variables like these.

Anybody have any ideas?

- JeremyB.[/code]

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

The additional code is making space (by moving the Stack Pointer by
12 bytes) for temp_reply on the stack. If it's causing trouble, the first
guess is that you're encountering a stack overflow.

If you're really running That close, it's probably a good time to audit your
stack usage, or at least use .data+.bss size to estimate how much
stack space you actually have.

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

If its just making stack space, why would it disable interrupts? .. also, I've got about 350 bytes free for stack, so I don't think I have an overflow problem, though I will check anyway.

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

> If its just making stack space, why would it disable interrupts?

They are only disabled while manipulating the stack pointer.

If you look at the assembly code generated by the compiler rather than
a disassembler listing ("make foo.s" if your C file is named foo.c),
it will get more obvious that this code saves and restores SREG. That
will also re-enable the interrupts.

Jörg Wunsch

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