von
tt (Gast)
28.07.2007 21:41
Kann ich in C ein Array von Unions anlegen und wie greife ich darauf zu?
Ich hab es so probiert:
typedef union
{
uint16_t i16;
struct
{
uint8_t l;
uint8_t h;
}i8;
} un_i16;
volatile un_i16 ust1_data[30];
folgender Zugriffsveruch klappt nicht:
SSP1BUF=ust1_data.i8.h[3];
Was tun?
von
déjà vu (Gast)
28.07.2007 21:46
von
déjà vu (Gast)
28.07.2007 21:52
>(ust1_data[3]).h ?
geht mit1 typedef union
2 {
3 uint16_t i16 ;
4 struct
5 {
6 uint8_t l ;
7 uint8_t h ;
8 };
9 } un_i16 ;
ansonsten halt (ust1_data[3]).i8.h ...
von
tt (Gast)
28.07.2007 21:53
Danke, guter Ansatz
ust1_data[3].i8.h
bringt keine Fehlermeldung mehr.
von
Peter (Gast)
28.07.2007 21:57
die klammern brauchst du nicht: 1 SSP1BUF = ust1_data [ 3 ]. i8 . h ;
übrigens ist das keine gute idee, auf die beiden bytes eine 16-bit
wertes zuzugreifen.
besser: 1 uint16_t x = 0x1234 ;
2 uint8_t lobyte = x & 0xff ; // 0x34
3 uint8_t hibyte = x >> 8 ; // 0x12
von
Punktrichter (Gast)
28.07.2007 22:04
Doch, seine Art, auf beide Byte zuzugreifen kostet keine Rechenzeit und
verbraucht minimal Speicherplatz.
Das kann man bei Deiner (insbesonder die Highbytevariante) nicht
behaupten.
von
Ralph (Gast)
28.07.2007 22:12
probier es mal so
SSP1BUF=ust1_data[3].i8.h;
Punktrichter wrote:
> Doch, seine Art, auf beide Byte zuzugreifen kostet keine Rechenzeit und
> verbraucht minimal Speicherplatz.
> Das kann man bei Deiner (insbesonder die Highbytevariante) nicht
> behaupten.
Nein, weil das Ergebnis seiner Art nirgendwo festgelegt ist und
Plattform und Compiler abhängig ist.
Peter's Art verbraucht "normal" optimiert vermutlich genausolange - aber
man hat kein Problem mehr mit Compilerabhängigem Gedönsel
von
déjà vu (Gast)
28.07.2007 22:19
1 #include <stdint.h>
2 #include <avr/io.h>
3
4 typedef union
5 {
6 uint16_t i16 ;
7 struct
8 {
9 uint8_t l ;
10 uint8_t h ;
11 };
12 } un_i16 ;
13
14 volatile uint16_t x ;
15 volatile un_i16 y ;
16
17 int main ( void )
18 {
19 x = 0x1234 ;
20 y . i16 = 0x5678 ;
21
22 DDRB = x & 0xff ;;
23 PORTB = x >> 8 ;;
24 DDRC = y . l ;
25 PORTC = y . h ;
26 }
ergibt: 1 0000005c <main>:
2 volatile uint16_t x ;
3 volatile un_i16 y;
4
5 int main(void)
6 {
7 5c: cf e5 ldi r28, 0x5F ; 95
8 5e: d4 e0 ldi r29, 0x04 ; 4
9 60: de bf out 0x3e, r29 ; 62
10 62: cd bf out 0x3d, r28 ; 61
11 x = 0x1234;
12 64: 84 e3 ldi r24, 0x34 ; 52
13 66: 92 e1 ldi r25, 0x12 ; 18
14 68: 90 93 61 00 sts 0x0061, r25
15 6c: 80 93 60 00 sts 0x0060, r24
16 y.i16 = 0x5678;
17 70: 88 e7 ldi r24, 0x78 ; 120
18 72: 96 e5 ldi r25, 0x56 ; 86
19 74: 90 93 63 00 sts 0x0063, r25
20 78: 80 93 62 00 sts 0x0062, r24
21
22 DDRB = x & 0xff;;
23 7c: 80 91 60 00 lds r24, 0x0060
24 80: 90 91 61 00 lds r25, 0x0061
25 84: 87 bb out 0x17, r24 ; 23
26 PORTB = x >> 8;;
27 86: 80 91 60 00 lds r24, 0x0060
28 8a: 90 91 61 00 lds r25, 0x0061
29 8e: 89 2f mov r24, r25
30 90: 99 27 eor r25, r25
31 92: 88 bb out 0x18, r24 ; 24
32 DDRC = y.l;
33 94: 80 91 62 00 lds r24, 0x0062
34 98: 84 bb out 0x14, r24 ; 20
35 PORTC = y.h;
36 9a: 80 91 63 00 lds r24, 0x0063
37 9e: 85 bb out 0x15, r24 ; 21
38 }
39 a0: 80 e0 ldi r24, 0x00 ; 0
40 a2: 90 e0 ldi r25, 0x00 ; 0
41 a4: 00 c0 rjmp .+0 ; 0xa6 <_exit>
42
43 000000a6 <_exit>:
44 a6: ff cf rjmp .-2 ; 0xa6 <_exit>
daran sieht man ganz deutlich, dass die union-variante vorteile hat.
von
déjà vu (Gast)
28.07.2007 22:21
hmm, wer hat denn die doppelten ;; da reingemogelt? aendert aber eh
nichts...
von
Peter (Gast)
28.07.2007 22:26
> daran sieht man ganz deutlich, dass die union-variante vorteile hat.
nein, daran sieht man, dass dein compiler nichts taugt.
von
déjà vu (Gast)
28.07.2007 22:27
achja, kompiliert mit avr-gcc, optimierung -Os
1 avr-gcc -c -mmcu=atmega8 -I. -gstabs -DF_CPU=8000000UL -Os -Wall -Wstrict-prototypes -std=gnu99 main.c -o main.o
2 avr-gcc -mmcu=atmega8 -I. -gstabs -DF_CPU=8000000UL -Os -Wall -Wstrict-prototypes -std=gnu99 main.o --output main.elf -lm
3 avr-objcopy -O ihex -R .eeprom main.elf main.hex
von
déjà vu (Gast)
28.07.2007 22:27
>nein, daran sieht man, dass dein compiler nichts taugt.
dann kompilier mein beispiel bitte mal mit deinem kompiler und poste das
asm-listing
von
Peter (Gast)
28.07.2007 22:41
> dann kompilier mein beispiel bitte mal mit deinem kompiler und poste das
> asm-listing
ich zeig dir mal'n output vom IAR für ARM :1 typedef unsigned char uint8_t ;
2 typedef unsigned short uint16_t ;
3
4 typedef union
5 {
6 uint16_t i16 ;
7 struct
8 {
9 uint8_t l ;
10 uint8_t h ;
11 } i8 ;
12 } un_i16 ;
13
14 int main ()
15 {
16 un_i16 x ;
17 uint16_t y ;
18 volatile uint8_t a , b , c , d ;
19
20 x . i16 = 0x1234 ;
21 y = 0x1234 ;
22
23 a = x . i8 . l ;
24 b = x . i8 . h ;
25
26 c = y & 0xff ;
27 d = y >> 8 ;
28 }
ergibt: 1 1 #include <stdlib.h>
2 2 #include <string.h>
3 3
4 4 typedef unsigned char uint8_t;
5 5 typedef unsigned short uint16_t;
6 6
7 7 typedef union
8 8 {
9 9 uint16_t i16;
10 10 struct
11 11 {
12 12 uint8_t l;
13 13 uint8_t h;
14 14 }i8;
15 15 } un_i16;
16 16
17
18 \ In segment CODE, align 4, keep-with-next
19 17 int main()
20 18 {
21 \ main:
22 \ 00000000 04D04DE2 SUB SP,SP,#+4
23 19 un_i16 x;
24 20 uint16_t y;
25 21 volatile uint8_t a,b,c,d;
26 22
27 23 x.i16 = 0x1234;
28 \ 00000004 3410A0E3 MOV R1,#+52
29 \ 00000008 481D81E3 ORR R1,R1,#0x1200
30 \ 0000000C B210CDE1 STRH R1,[SP, #+2]
31 24 y = 0x1234;
32 \ 00000010 3400A0E3 MOV R0,#+52
33 \ 00000014 480D80E3 ORR R0,R0,#0x1200
34 25
35 26 a = x.i8.l;
36 \ 00000018 0220DDE5 LDRB R2,[SP, #+2]
37 \ 0000001C 0020CDE5 STRB R2,[SP, #+0]
38 27 b = x.i8.h;
39 \ 00000020 0320DDE5 LDRB R2,[SP, #+3]
40 \ 00000024 0020CDE5 STRB R2,[SP, #+0]
41 28
42 29 c = y & 0xff;
43 \ 00000028 0000CDE5 STRB R0,[SP, #+0]
44 30 d = y >> 8;
45 \ 0000002C 2004B0E1 LSRS R0,R0,#+8
46 \ 00000030 0000CDE5 STRB R0,[SP, #+0]
47 31 }
48 \ 00000034 0000A0E3 MOV R0,#+0
49 \ 00000038 04D08DE2 ADD SP,SP,#+4 ;; stack cleaning
50 \ 0000003C 1EFF2FE1 BX LR ;; return
51
52 Maximum stack usage in bytes:
53
54 Function CSTACK
55 -------- ------
56 main 4
57
58
59 Segment part sizes:
60
61 Function/Label Bytes
62 -------------- -----
63 main 64
64 Others 4
65
66
67 68 bytes in segment CODE
68
69 64 bytes of CODE memory (+ 4 bytes shared)
70
71 Errors: none
72 Warnings: none
von
déjà vu (Gast)
28.07.2007 22:48
>ich zeig dir mal'n output vom IAR für ARM :
aendert sich was, wenn x und y auch als volatile deklariert werden?
hier mal dein beispiel mit avr-gcc:1 int main(void)
2 {
3 5c: cb e5 ldi r28, 0x5B ; 91
4 5e: d4 e0 ldi r29, 0x04 ; 4
5 60: de bf out 0x3e, r29 ; 62
6 62: cd bf out 0x3d, r28 ; 61
7 un_i16 x;
8 uint16_t y;
9 volatile uint8_t a,b,c,d;
10
11 x.i16 = 0x1234;
12 64: 84 e3 ldi r24, 0x34 ; 52
13 66: 92 e1 ldi r25, 0x12 ; 18
14 y = 0x1234;
15
16 a = x.i8.l;
17 68: 89 83 std Y+1, r24 ; 0x01
18 b = x.i8.h;
19 6a: 9a 83 std Y+2, r25 ; 0x02
20
21 c = y & 0xff;
22 6c: 8b 83 std Y+3, r24 ; 0x03
23 d = y >> 8;
24 6e: 82 e1 ldi r24, 0x12 ; 18
25 70: 90 e0 ldi r25, 0x00 ; 0
26 72: 8c 83 std Y+4, r24 ; 0x04
27 }
von
déjà vu (Gast)
28.07.2007 23:00
vorweg schonmal das ergebnis von avr-gcc mit x und y als volatile: 1 int main(void)
2 {
3 5c: c7 e5 ldi r28, 0x57 ; 87
4 5e: d4 e0 ldi r29, 0x04 ; 4
5 60: de bf out 0x3e, r29 ; 62
6 62: cd bf out 0x3d, r28 ; 61
7 volatile un_i16 x;
8 volatile uint16_t y;
9 volatile uint8_t a,b,c,d;
10
11 x.i16 = 0x1234;
12 64: 84 e3 ldi r24, 0x34 ; 52
13 66: 92 e1 ldi r25, 0x12 ; 18
14 68: 9a 83 std Y+2, r25 ; 0x02
15 6a: 89 83 std Y+1, r24 ; 0x01
16 y = 0x1234;
17 6c: 9c 83 std Y+4, r25 ; 0x04
18 6e: 8b 83 std Y+3, r24 ; 0x03
19
20 a = x.i8.l;
21 70: 89 81 ldd r24, Y+1 ; 0x01
22 72: 8d 83 std Y+5, r24 ; 0x05
23 b = x.i8.h;
24 74: 8a 81 ldd r24, Y+2 ; 0x02
25 76: 8e 83 std Y+6, r24 ; 0x06
26
27 c = y & 0xff;
28 78: 8b 81 ldd r24, Y+3 ; 0x03
29 7a: 9c 81 ldd r25, Y+4 ; 0x04
30 7c: 8f 83 std Y+7, r24 ; 0x07
31 d = y >> 8;
32 7e: 8b 81 ldd r24, Y+3 ; 0x03
33 80: 9c 81 ldd r25, Y+4 ; 0x04
34 82: 89 2f mov r24, r25
35 84: 99 27 eor r25, r25
36 86: 88 87 std Y+8, r24 ; 0x08
37 }
von
Peter (Gast)
28.07.2007 23:06
> aendert sich was, wenn x und y auch als volatile deklariert werden?
ja, es kommt jedesmal eine instruction dazu, weil der zugriff auf die
variablen ja jedesmal neu erfolgen muss.
btw, am besten siehts aus, wenn man die variablen nicht in der funktion
hat:1 26 a = x.i8.l;
2 \ 00000014 0010D0E5 LDRB R1,[R0, #+0]
3 \ 00000018 0410C0E5 STRB R1,[R0, #+4]
4 27 b = x.i8.h;
5 \ 0000001C 0110D0E5 LDRB R1,[R0, #+1]
6 \ 00000020 0510C0E5 STRB R1,[R0, #+5]
7 28
8 29 c = y & 0xff;
9 \ 00000024 3410A0E3 MOV R1,#+52
10 \ 00000028 0610C0E5 STRB R1,[R0, #+6]
11 30 d = y >> 8;
12 \ 0000002C 1210A0E3 MOV R1,#+18
13 \ 00000030 0710C0E5 STRB R1,[R0, #+7]
kein shift und keine und-verknüpfung.
globale/statische objekte mögen wohl alle compiler lieber ;-)
Mich würde mal interessieren welcher Compiler den in der Praxis Probleme
mit der union Variante hat.
Ich benutze eigentlich auch immer die union Variante.
Die für mich entscheidenden Vorteile:
- Garantiert eine kurze Laufzeit (unabhängig von Qualität des
Compilers...)
- Deutlich übersichtlicher als die mask/shift Variante.
- Bisher hatte ich noch keine Probleme ;)
Was ich mir problematisch vorstelle sind big/little endian Systeme.
Aber da habe ich doch das selbe Problem auch beim shiften?
Wenn das Probleme verursacht gewinnt aber auch hier wieder die union
Variante, dann definiert man halt zwei unions, je nach endian.
Beim shiften müsste man alles direkt im Code ändern
von
Peter (Gast)
28.07.2007 23:18
> Was ich mir problematisch vorstelle sind big/little endian Systeme.
das ist der hauptgrund, weshalb man es nicht mit unions machen sollte.
> Aber da habe ich doch das selbe Problem auch beim shiften?
nein, shift und andere operatoren sind unabhängig von der internen
repräsentation der daten.
von
déjà vu (Gast)
28.07.2007 23:18
nungut, ich geb mich geschlagen. (avr-)gcc braucht den umweg ueber die
union, um (in diesem fall) effizienten code zu liefern.
das einzige, womit ich nicht einverstanden bin ist die aussage von
simon:
>Peter's Art verbraucht "normal" optimiert vermutlich genausolange - aber
>man hat kein Problem mehr mit Compilerabhängigem Gedönsel
unions sind c-standard und nicht "compilerabhaengiges gedoensel". das
man sie benutzen muss, um das gleiche ergebnis wie mit teuren
bezahlkompilern zu erhalten ist aergerlich, aber funktionieren tuts mit
beiden.
so long, déjà vu.
von
Peter (Gast)
28.07.2007 23:20
so mach' ich das immer :-) 1 #define LOBYTE(x) ((x)&0xff)
2 #define HIBYTE(x) ((x)>>8)
déjà vu wrote:
> unions sind c-standard und nicht "compilerabhaengiges gedoensel".
Ja, unions sind c-standard. Aber nur solange, wie man auf gleichen wegen
die Daten schreibt/liest. (Sprich: über die gleiche member-variable
reinschreibt, wie man rausliest)
Wenn man unterschiedliche Union-member zum schreiben und lesen benutzt
ist das Verhalten nicht mehr im C-Standard definiert.
von
déjà vu (Gast)
28.07.2007 23:24
nachtrag:
rein interessehalber, wie siehts eigentlich andersrum aus?
1 y . l = 0x34 ;
2 y . h = 0x12 ;
im gegensatz zu: 1 x = 0x34 ;
2 x |= 0x12 << 8 ;
kann iar auch das optimieren?
von
Peter (Gast)
28.07.2007 23:24
> unions sind c-standard und nicht "compilerabhaengiges gedoensel".
ja, aber es ist nicht alles genau definiert. der compiler könnte
padding-bytes einsetzen (um zugriffe zu optimieren) und schon passen
deine bytes nicht mehr. unions sind dazu da, speicherplatz zu sparen. so
wie du sie verwendest, ist das verhalten undefiniert (auch wenn's in der
realität oft gut geht).
von
déjà vu (Gast)
28.07.2007 23:25
>Wenn man unterschiedliche Union-member zum schreiben und lesen benutzt
>ist das Verhalten nicht mehr im C-Standard definiert.
wieder was gelernt.
von
déjà vu (Gast)
28.07.2007 23:26
>so mach' ich das immer :-)
>#define LOBYTE(x) ((x)&0xff)
>#define HIBYTE(x) ((x)>>8)
das geht aber so dann nicht mehr:
oder?
déjà vu wrote:
>>so mach' ich das immer :-)
>>#define LOBYTE(x) ((x)&0xff)
>>#define HIBYTE(x) ((x)>>8)
>
> das geht aber so dann nicht mehr:
>
> oder?
Stimmt. Wozu auch? ;)
1 uint16_t y ;
2
3 y = 0x12 ; // Low byte ist jetzt 0x12
4 y = 0x1200 // High byte ist jetzt 0x12
von
déjà vu (Gast)
28.07.2007 23:36
>Stimmt. Wozu auch? ;)
dann eben so:1 y . h = uart_getc ();
2 y . l = uart_getc ();
3
4 x = (( uint16_t ) uart_getc ()) << 8 | uart_getc ();
von
déjà vu (Gast)
28.07.2007 23:40
bzw, um im kontext zu bleiben: 1 LOBYTE ( x ) = uart_getc ();
2 HIBYTE ( x ) = uart_getc ();
mir ist schon klar, dass das nicht geht; aber gibts dafuer ein
sinnvolles define?
1 #define LOBYTE(x) ( ((un_i16)(x)).l )
geht naemlich nicht...
von
Peter (Gast)
28.07.2007 23:41
oder so 1 #define MAKEWORD(x,y) (((uint16_t)(x)<<8)|(y))
:-)
Peter wrote:
> oder so
> 1 #define MAKEWORD(x,y) (((uint16_t)(x)<<8)|(y))
> :-)
Jou, oder mit weniger Funktionalität
1 #define MAKEHI(x) ((x) << 8)
von
Peter (Gast)
28.07.2007 23:47
> Jou, oder mit weniger Funktionalität
> #define MAKEHI(x) ((x) << 8)
hehe, wenn 'x' ein 'char' ist, gibt das immer 0
Peter wrote:
>> Jou, oder mit weniger Funktionalität
>> #define MAKEHI(x) ((x) << 8)
> hehe, wenn 'x' ein 'char' ist, gibt das immer 0
Mist, da hast du recht.
1 #define MAKEHI(x) ( (uint16_t) (x) << 8)
von
déjà vu (Gast)
28.07.2007 23:57
ok, mal ein ein konkretes beispiel(vorraussetzung: union-trick
notwendig, da avr-gcc): 1 ISR ( TIMER0_OVF_vect )
2 {
3 register convert16to8_t counter ;
4 counter . u8h = soft_counter ;
5 counter . u8l = TCNT2 ;
6 if ( ( TIFR & ( 1 << TOV2 )) && ( counter . u8l < 0x7f ) )
7 counter . u8h ++ ;
8 pitch_value = counter . u16 - pitch_counter ;
9 pitch_counter = counter . u16 ;
10 status_set ( STATUS_PITCH );
11 }
gaebe es da ein #define, mit dem ich das schreiben koennte:
danach suche ich naemlich schon laenger.
1 #define HIBYTE(x) ( ((un_i16)(x)).h )
funktioniert wiegesagt nur als r-value, nicht als l-value.
von
Peter (Gast)
29.07.2007 00:04
> HIBYTE(counter)++;
1 #define INCREMENT_HI_BYTE(x) ((x)+=0x100)
;-)
von
déjà vu (Gast)
29.07.2007 00:04
und unabhaengig davon: 1 ISR(TIMER0_OVF_vect)
2 {
3 37a: 1f 92 push r1
4 37c: 0f 92 push r0
5 37e: 0f b6 in r0, 0x3f ; 63
6 380: 0f 92 push r0
7 382: 11 24 eor r1, r1
8 384: 2f 93 push r18
9 386: 3f 93 push r19
10 388: 8f 93 push r24
11 register convert16to8_t counter;
12 counter.u8h = soft_counter;
13 38a: 32 2d mov r19, r2
14 counter.u8l = TCNT2;
15 38c: 84 b5 in r24, 0x24 ; 36
16 38e: 28 2f mov r18, r24
17 if ( (TIFR & (1<<TOV2)) && (counter.u8l < 0x7f) )
18 390: 08 b6 in r0, 0x38 ; 56
19 392: 06 fe sbrs r0, 6
20 394: 03 c0 rjmp .+6 ; 0x39c <__vector_9+0x22>
21 396: 8f 37 cpi r24, 0x7F ; 127
22 398: 08 f4 brcc .+2 ; 0x39c <__vector_9+0x22>
23 counter.u8h++;
24 39a: 3f 5f subi r19, 0xFF ; 255
25 pitch_value = counter.u16 - pitch_counter;
26 39c: 49 01 movw r8, r18
27 39e: 8c 18 sub r8, r12
28 3a0: 9d 08 sbc r9, r13
29 pitch_counter = counter.u16;
30 3a2: 69 01 movw r12, r18
31 status_set(STATUS_PITCH);
32 3a4: 00 9a sbi 0x00, 0 ; 0
33 3a6: 8f 91 pop r24
34 3a8: 3f 91 pop r19
35 3aa: 2f 91 pop r18
36 3ac: 0f 90 pop r0
37 3ae: 0f be out 0x3f, r0 ; 63
38 3b0: 0f 90 pop r0
39 3b2: 1f 90 pop r1
40 3b4: 18 95 reti
41 }
das mach mir erstmal einer in c nach... ;)
von
déjà vu (Gast)
29.07.2007 00:06
>#define INCREMENT_HI_BYTE(x) ((x)+=0x100)
dann bleib ich lieber bei meinem "union gedoensel" :P
von
Peter (Gast)
29.07.2007 00:49
> ISR(TIMER0_OVF_vect)
> {
> register convert16to8_t counter;
> counter.u8h = soft_counter;
> counter.u8l = TCNT2;
> if ( (TIFR & (1<<TOV2)) && (counter.u8l < 0x7f) )
> counter.u8h++;
> pitch_value = counter.u16 - pitch_counter;
> pitch_counter = counter.u16;
> status_set(STATUS_PITCH);
>}
probier mal so:1 ISR ( TIMER0_OVF_vect )
2 {
3 register uint16_t counter ;
4 counter = (( uint16_t ) soft_counter << 8 ) | TCNT2 ;
5 if ( ( TIFR & ( 1 << TOV2 )) && ( counter & 0xff ) < 0x7f ) )
6 counter += 0x100 ;
7 pitch_value = counter - pitch_counter ;
8 pitch_counter = counter ;
9 status_set ( STATUS_PITCH );
10 }
oder so (mit 8 bit variable) 1 ISR ( TIMER0_OVF_vect )
2 {
3 register uint8_t counter = soft_counter ;
4 if ( ( TIFR & ( 1 << TOV2 )) && ( TCNT2 < 0x7f ) )
5 counter ++ ;
6 pitch_value = (( uint16_t ) counter << 8 ) | TCNT2 ;
7 pitch_counter = pitch_value ;
8 pitch_value -= pitch_counter ;
9 status_set ( STATUS_PITCH );
10 }
ich weiss natürlich nicht ob's noch geht (wegen des TCNT2)...
von
déjà vu (Gast)
29.07.2007 01:03
beide versionen machen die ISR nur laenger, war ja auch nicht anders zu
erwarten. mir gings eigentlich auch um ein universelles #define fuer r-
und l-values. das man das auch "konventionell" schreiben kann, war mir
schon klar. trotzdem danke, dass du dir die muehe gemacht hast, meinen
code umzuschreiben. aber "lesbarer" wirds dadurch nicht wirklich. das
mit dem #define waere halt schoen, da man sich die .u16 sparen koennte.
aber letztlich kommts ja eh nur auf den bytecode an. und den hab ich mir
schon mit komischen c-konstrukten zurechtgebogen ;)
der vollstaendigkeit halber: 1 ISR(TIMER0_OVF_vect)
2 {
3 37a: 1f 92 push r1
4 37c: 0f 92 push r0
5 37e: 0f b6 in r0, 0x3f ; 63
6 380: 0f 92 push r0
7 382: 11 24 eor r1, r1
8 384: 2f 93 push r18
9 386: 3f 93 push r19
10 388: 8f 93 push r24
11 38a: 9f 93 push r25
12 register uint16_t counter;
13 counter = ((uint16_t)soft_counter << 8) | TCNT2;
14 38c: 82 2d mov r24, r2
15 38e: 99 27 eor r25, r25
16 390: 38 2f mov r19, r24
17 392: 22 27 eor r18, r18
18 394: 84 b5 in r24, 0x24 ; 36
19 396: 99 27 eor r25, r25
20 398: 28 2b or r18, r24
21 39a: 39 2b or r19, r25
22 if ( (TIFR & (1<<TOV2)) && (counter & 0xff) < 0x7f)
23 39c: 08 b6 in r0, 0x38 ; 56
24 39e: 06 fe sbrs r0, 6
25 3a0: 04 c0 rjmp .+8 ; 0x3aa <__vector_9+0x30>
26 3a2: 2f 37 cpi r18, 0x7F ; 127
27 3a4: 10 f4 brcc .+4 ; 0x3aa <__vector_9+0x30>
28 counter += 0x100;
29 3a6: 20 50 subi r18, 0x00 ; 0
30 3a8: 3f 4f sbci r19, 0xFF ; 255
31 pitch_value = counter - pitch_counter;
32 3aa: 49 01 movw r8, r18
33 3ac: 8c 18 sub r8, r12
34 3ae: 9d 08 sbc r9, r13
35 pitch_counter = counter;
36 3b0: 69 01 movw r12, r18
37 status_set(STATUS_PITCH);
38 3b2: 00 9a sbi 0x00, 0 ; 0
39 3b4: 9f 91 pop r25
40 3b6: 8f 91 pop r24
41 3b8: 3f 91 pop r19
42 3ba: 2f 91 pop r18
43 3bc: 0f 90 pop r0
44 3be: 0f be out 0x3f, r0 ; 63
45 3c0: 0f 90 pop r0
46 3c2: 1f 90 pop r1
47 3c4: 18 95 reti
48 }
1 ISR(TIMER0_OVF_vect)
2 {
3 37a: 1f 92 push r1
4 37c: 0f 92 push r0
5 37e: 0f b6 in r0, 0x3f ; 63
6 380: 0f 92 push r0
7 382: 11 24 eor r1, r1
8 384: 2f 93 push r18
9 386: 3f 93 push r19
10 388: 8f 93 push r24
11 38a: 9f 93 push r25
12 register uint8_t counter = soft_counter;
13 38c: 92 2d mov r25, r2
14 if ( (TIFR & (1<<TOV2)) && (TCNT2 < 0x7f) )
15 38e: 08 b6 in r0, 0x38 ; 56
16 390: 06 fe sbrs r0, 6
17 392: 04 c0 rjmp .+8 ; 0x39c <__vector_9+0x22>
18 394: 84 b5 in r24, 0x24 ; 36
19 396: 8f 37 cpi r24, 0x7F ; 127
20 398: 08 f4 brcc .+2 ; 0x39c <__vector_9+0x22>
21 counter++;
22 39a: 9f 5f subi r25, 0xFF ; 255
23 pitch_value = ((uint16_t)counter << 8) | TCNT2;
24 39c: 89 2f mov r24, r25
25 39e: 99 27 eor r25, r25
26 3a0: 38 2f mov r19, r24
27 3a2: 22 27 eor r18, r18
28 3a4: 84 b5 in r24, 0x24 ; 36
29 3a6: 99 27 eor r25, r25
30 pitch_counter = pitch_value;
31 3a8: 69 01 movw r12, r18
32 3aa: c8 2a or r12, r24
33 3ac: d9 2a or r13, r25
34 pitch_value -= pitch_counter;
35 3ae: 88 24 eor r8, r8
36 3b0: 99 24 eor r9, r9
37 status_set(STATUS_PITCH);
38 3b2: 00 9a sbi 0x00, 0 ; 0
39 3b4: 9f 91 pop r25
40 3b6: 8f 91 pop r24
41 3b8: 3f 91 pop r19
42 3ba: 2f 91 pop r18
43 3bc: 0f 90 pop r0
44 3be: 0f be out 0x3f, r0 ; 63
45 3c0: 0f 90 pop r0
46 3c2: 1f 90 pop r1
47 3c4: 18 95 reti
48 }
so long, déjà vu.
von
Peter (Gast)
29.07.2007 01:26
> beide versionen machen die ISR nur laenger, war ja auch nicht anders zu
> erwarten.
ja, schade :-(
den GCC sollte man eben mit vorsicht geniessen, aber wenn man die tricks
kennt...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.