- posted
18 years ago
inline w WinAVR
- Vote on answer
- posted
18 years ago
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
- Vote on answer
- posted
18 years ago
- Vote on answer
- posted
18 years ago
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.
- Vote on answer
- posted
18 years ago
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.
- Vote on answer
- posted
18 years ago
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 :-)