inline w WinAVR

Loading thread data ...

Mon, 14 Nov 2005 08:22:15 +0100, na pl.misc.elektronika, Bogdan Gutknecht napisał(a):

Dla kodu w C użyj dla handlera atrybutu naked - będzie bez prologu i epilogu, ale całą ochronę rejestrów i reti trzeba wpisać samemu. A jak ma byc rzeczywiście max szybkość to chyba najpewniej będzie wyrzucić obsługę do modułu .S i popisać w czystym asm np. jakoś tak:

[..] // s interrupt

//#define __SFR_OFFSET 0 #include <avr/io.h>

.global SIG_INTERRUPT1 .section .text,"ax",@progbits

SIG_INTERRUPT1: push r24 ldi r24,0x40 out _SFR_IO_ADDR(PORTB),r24 pop r24 reti

Reply to
Jurek Szczesiul
Reply to
Bogdan Gutknecht

Mon, 14 Nov 2005 09:15:36 +0100, na pl.misc.elektronika, Bogdan Gutknecht napisał(a):

Ja w sumie tak samo :-) Podsunąłem typowe opisywane rozwiązania - sam ich też nie miałem potrzeby używać. Fakt, że avr-gcc nie analizuje użycia rejestrów w funkcjach wywoływanych z handlera przerwania i na wszelki wypadek pcha na stos wszystko ( chyba głownie o to tu chodzi ? ) co niepotrzebnie wydłuża. Więc albo pisać wszystko bezpośrednio w handlerze, albo dopomóc sobie makrami, albo jednak dalej próbować z inline - w przypadku prostych funkcji to działa, na przykład :

extern void Little(char x);

void Little(char x) { PORTB=x; }

SIGNAL (SIG_INTERRUPT0) { //PORTB=0x20; Little(0x20); } generuje dość przeraźliwie nadmiarowy kod :

SIGNAL (SIG_INTERRUPT0) { 96: 1f 92 push r1 98: 0f 92 push r0 9a: 0f b6 in r0, 0x3f ; 63 9c: 0f 92 push r0 9e: 11 24 eor r1, r1 a0: 2f 93 push r18 a2: 3f 93 push r19 a4: 4f 93 push r20 a6: 5f 93 push r21 a8: 6f 93 push r22 aa: 7f 93 push r23 ac: 8f 93 push r24 ae: 9f 93 push r25 b0: af 93 push r26 b2: bf 93 push r27 b4: ef 93 push r30 b6: ff 93 push r31 //PORTB=0x20; Little(0x20); b8: 80 e2 ldi r24, 0x20 ; 32 ba: eb df rcall .-42 ; 0x92 bc: ff 91 pop r31 be: ef 91 pop r30 c0: bf 91 pop r27 c2: af 91 pop r26 c4: 9f 91 pop r25 c6: 8f 91 pop r24 c8: 7f 91 pop r23 ca: 6f 91 pop r22 cc: 5f 91 pop r21 ce: 4f 91 pop r20 d0: 3f 91 pop r19 d2: 2f 91 pop r18 d4: 0f 90 pop r0 d6: 0f be out 0x3f, r0 ; 63 d8: 0f 90 pop r0 da: 1f 90 pop r1 dc: 18 95 reti

Natomiast deklaracja inline :

extern inline void Little(char x);

natychmiast robi to co chcemy ( wynik dla -Os )

SIGNAL (SIG_INTERRUPT0) { 96: 1f 92 push r1 98: 0f 92 push r0 9a: 0f b6 in r0, 0x3f ; 63 9c: 0f 92 push r0 9e: 11 24 eor r1, r1 a0: 8f 93 push r24 a2: 80 e2 ldi r24, 0x20 ; 32 a4: 88 bb out 0x18, r24 ; 24 a6: 8f 91 pop r24 a8: 0f 90 pop r0 aa: 0f be out 0x3f, r0 ; 63 ac: 0f 90 pop r0 ae: 1f 90 pop r1 b0: 18 95 reti

Więc może po paru różnych podejściach uzyska się wystarczający rezultat.

Reply to
Jurek Szczesiul

Jurek Szczesiul przemówił ludzkim głosem:

Ale tendencyjny przykład dobrałeś :-). Gcc nie odkłada wszystkich rejestrów na stos jak jest w stanie śledzić ich zużycie. A że nie śledzi co się dzieje wewnątrz wywoływanych funkcji to profilaktycznie kładzie na stos wszystko. Wystarczy nie wywoływać funkcji z wnętrza przerwania.

Reply to
Zbych

Mon, 14 Nov 2005 21:39:14 +0100, na pl.misc.elektronika, Zbych napisał(a):

No, ja właśnie o tym samym , hau, miau :-)

Reply to
Jurek Szczesiul

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.