inline w WinAVR

Nov 14, 2005 5 Replies

Chcia³bym przyspieszyæ krytyczne operacje w przerwaniu. Chodzi o programow± obs³ugê transmisji szeregowej. Przerwanie jest co 34us, a linie s± cztery. Je¶li obs³ugê umieszczê w procedurze to mam ³adny program, ale wolny - tracê na ka¿dorazowym wywo³aniu prawie 5 us, co daje razem 20. I tu mam problem. Próbowa³em zastosowaæ specyfikator inline, niestety kompilator jakby go nie widzia³. Ma do tego zreszt± prawo wed³ug specyfikacji. Czy mogê w jaki¶ sposób zmusiæ go do przepisywania kodu zamiast wywo³ywania procedury?



BG


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

U¿ytkownik "Jurek Szczesiul" snipped-for-privacy@wycin.ep.com.pl> napisa³ w wiadomo¶ci news:1il1pzelkigyr$. snipped-for-privacy@40tude.net...

Jedn± ze szczê¶liwszych chwil w moim ¿yciu zawodowym by³o odkrycie gcc-avr. Nie muszê siê martwiæ o alokacjê zmiennych, zabezpieczanie na stosie, arytmetykê i wiele innych, koniecznych, aczkolwiek nu¿±cych rzeczy, które dodatkowo mog± byæ przyczyn± kretyñskich b³êdów. Bêdê wiêc próbowa³ nie schodziæ na "ni¿szy" poziom tak d³ugo jak siê da. Tym bardziej, ¿e w tym przerwaniu ma byæ nie tylko odczytywanie i zapis linii, ale ca³y automat odczytu i zapisu oraz obs³uga bufora. Chyba jednak wolê zmniejszyæ szybko¶æ transmisji do 4800, ni¿ pisaæ w asemblerze (starzejê siê - zosta³y mi tylko ciep³e kapcie i C).

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.

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.

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 :-)

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required