Forum: Compiler & IDEs GCC mappt Static-Variable auf ein I/O-Register


von Flex (Gast)


Lesenswert?

Hallo allerseits,

unter welchen Umständen macht der GCC eigentlich sowas?
uart_address ist augenscheinlich auf 0x0060. Das ist normalerweise 
WDTCSR. Was heißt normalerweise? Das ist hardwarebedingt, von daher 
sollte es ja eigentlich nicht passieren...

Kompiliert mit "gcc version 4.7.1 20120322 (prerelease) (GCC)" für 
"atmega168p".
1
ISR (USART_RX_vect) {
2
    38a0:  1f 92         push  r1
3
    38a2:  0f 92         push  r0
4
    38a4:  0f b6         in  r0, 0x3f  ; 63
5
    38a6:  0f 92         push  r0
6
    38a8:  11 24         eor  r1, r1
7
    38aa:  2f 93         push  r18
8
    38ac:  8f 93         push  r24
9
    38ae:  9f 93         push  r25
10
    38b0:  ef 93         push  r30
11
    38b2:  ff 93         push  r31
12
  uint8_t c = UDR0;
13
    38b4:  80 91 c6 00   lds  r24, 0x00C6
14
15
  static uint8_t uart_address = 0;
16
  uint8_t address = uart_address;
17
    38b8:  20 91 60 00   lds  r18, 0x0060
18
19
  if (uart_command) return;
20
    38bc:  90 91 64 00   lds  r25, 0x0064
21
    38c0:  91 11         cpse  r25, r1
22
    38c2:  29 c0         rjmp  .+82       ; 0x3916 <__vector_18+0x76>
23
24
  if ((c >= '0') && (c <= '9')) c -= '0';
25
    38c4:  98 2f         mov  r25, r24
26
    38c6:  90 53         subi  r25, 0x30  ; 48
27
    38c8:  9a 30         cpi  r25, 0x0A  ; 10
28
    38ca:  a0 f0         brcs  .+40       ; 0x38f4 <__vector_18+0x54>
29
  else if ((c >= 'a') && (c <= 'f')) c -= 'a' - 10;
30
    38cc:  91 53         subi  r25, 0x31  ; 49
31
    38ce:  96 30         cpi  r25, 0x06  ; 6
32
    38d0:  08 f4         brcc  .+2        ; 0x38d4 <__vector_18+0x34>
33
    38d2:  04 c0         rjmp  .+8        ; 0x38dc <__vector_18+0x3c>
34
  else if ((c >= 'A') && (c <= 'F')) c -= 'A' - 10;
35
    38d4:  98 2f         mov  r25, r24
36
    38d6:  91 54         subi  r25, 0x41  ; 65
37
    38d8:  96 30         cpi  r25, 0x06  ; 6
38
    38da:  10 f4         brcc  .+4        ; 0x38e0 <__vector_18+0x40>
39
    38dc:  96 5f         subi  r25, 0xF6  ; 246
40
    38de:  0a c0         rjmp  .+20       ; 0x38f4 <__vector_18+0x54>
41
  else {
42
    uint8_t size = address;
43
    size >>= 1;
44
    38e0:  26 95         lsr  r18
45
    uart_size = size;
46
    38e2:  20 93 63 00   sts  0x0063, r18
47
    uart_address = 0;
48
    38e6:  10 92 60 00   sts  0x0060, r1
49
    uart_command = uart_buffer.Byte[0];
50
    38ea:  80 91 65 00   lds  r24, 0x0065
51
    38ee:  80 93 64 00   sts  0x0064, r24
52
    return;
53
    38f2:  11 c0         rjmp  .+34       ; 0x3916 <__vector_18+0x76>
54
  }
55
  address >>= 1;
56
    38f4:  e2 2f         mov  r30, r18
57
    38f6:  e6 95         lsr  r30
58
  if (address >= sizeof(uart_buffer.Byte)) return;
59
    38f8:  e3 34         cpi  r30, 0x43  ; 67
60
    38fa:  68 f4         brcc  .+26       ; 0x3916 <__vector_18+0x76>
61
  uart_buffer.Byte[address] <<= 4;
62
    38fc:  f0 e0         ldi  r31, 0x00  ; 0
63
    38fe:  eb 59         subi  r30, 0x9B  ; 155
64
    3900:  ff 4f         sbci  r31, 0xFF  ; 255
65
    3902:  80 81         ld  r24, Z
66
    3904:  82 95         swap  r24
67
    3906:  80 7f         andi  r24, 0xF0  ; 240
68
    3908:  80 83         st  Z, r24
69
  uart_buffer.Byte[address] += c;
70
    390a:  80 81         ld  r24, Z
71
    390c:  89 0f         add  r24, r25
72
    390e:  80 83         st  Z, r24
73
  uart_address++;
74
    3910:  2f 5f         subi  r18, 0xFF  ; 255
75
    3912:  20 93 60 00   sts  0x0060, r18
76
}
77
    3916:  ff 91         pop  r31
78
    3918:  ef 91         pop  r30
79
    391a:  9f 91         pop  r25
80
    391c:  8f 91         pop  r24
81
    391e:  2f 91         pop  r18
82
    3920:  0f 90         pop  r0
83
    3922:  0f be         out  0x3f, r0  ; 63
84
    3924:  0f 90         pop  r0
85
    3926:  1f 90         pop  r1
86
    3928:  18 95         reti

von Flex (Gast)


Lesenswert?

Habe es auf die Linker-Option "-Wl,--gc-sections" eingegrenzt.

Folgendes Minimal-Beispiel kann jeder mal selbst testen:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
ISR (USART_RX_vect) {
5
  static uint8_t uart_address = 0;
6
  uart_address++;
7
}
8
9
int main() {
10
}

Mit "-Wl,--gc-sections" wandert uart_address nach 0x0060. Aber 
eigentlich darf das doch trotzdem nicht sein, oder??

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Sieht aus wie http://sourceware.org/PR13697

Was hilft ist mindestens eine Variable in .data zu haben:
1
void __attribute__((signal,externally_visible,used,naked))
2
__vector_1 (void)
3
{
4
  static char volatile a;
5
  a++;
6
}
7
8
char volatile dummy = 1;
9
10
int main()
11
{
12
    (void) dummy;
13
    return 0;
14
}

Wird das Lesen von dummy auskommentiert, gibt's falsche Werte.

Der Compiler übergibt per Linker-Spec ein -Tdata=0x800100 an ld, und 
wenn nix in .data ist, wird dies offenbar ignoriert und die binutils 
verwenden den Architektur-Default für avr5. Dieser ist 0x800060 für den 
RAM-Anfang, und danach richten sich dann auch .bss etc.

von Flex (Gast)


Lesenswert?

Hmmm, über Monate bekannt und noch nicht gefixt? Ich habe gestern und 
heute etliche Stunden nach dem Fehler gesucht. :((

Dein Workaround funktioniert. Aber schön ist das so nicht.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Flex schrieb:
> Hmmm, über Monate bekannt und noch nicht gefixt?

Von selbst oder duch Beten fixen sich eben keine Bugs...

Wenn es keiner macht, dann macht es keiner.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.