Krzysztof Urbanski
Guest
Sat Nov 06, 2004 6:02 pm
Witam
Niedawno zaczalem zabawe z AVRami. Napisalem sobie petle opoznien w
asemblerze pod AVRStudio. Teraz zabralem sie za avrgcc i chcialbym
funkcje opoznien napisac jako wstawki asemblerowe. W dokumentacji
wyczytalem ze mozna np. tak:
....
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
....
Problem w tym ze w wynikowym listingu pojawia sie tylko jeden nop.
Optymalizacje wylaczylem. Uzywam Avrside.
Moze jest jakis sposob zeby wywolywac funkcje napisane w calosci w asm
znajdujace sie w innych plikach ?
Pozdrawiam
Krzysztof Urbanski
krzysztof-u@[usun_to]wp.pl
Piotr Wyderski
Guest
Sat Nov 06, 2004 7:20 pm
Krzysztof Urbanski wrote:
Quote:
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
Sprobuj to zrobic w jednym bloku volatile:
asm volatile("\tnop\n" \
"\tnop\n" \
"\tnop\n");
Quote:
Problem w tym ze w wynikowym listingu pojawia sie tylko jeden nop.
Optymalizacje wylaczylem. Uzywam Avrside.
Deklaracja volatile zabrania zmieniac kompilatorowi
strukture bloku. Tylko IIRC dziala ona na _spojnych_
blokach, a Ty utworzyles trzy rozne bloki, wiec
teoretycznie kompilator mogl sobie przy nich
pomajstrowac.
Quote:
Moze jest jakis sposob zeby wywolywac funkcje napisane
w calosci w asm znajdujace sie w innych plikach ?
extern "C" sygnatura_funkcji();
Jesli nazwa funkcji asemblerowej jest "dziwna", to mozna
sobie jeszcze pomoc podajac pelna nazwe za pomoca
__attribute__((__allias__)). Najlepiej jesli funkcje nie
biora parametrow i nie zwracaja wynikow; w przeciwnym
razie musisz sie zapoznac z tzw. konwencjami wywolania.
Tylko pamietaj, ze wstawka to cos innego niz zewnetrzna
funkcja, wiec staraj sie nie naduzywac jednego mechanizmu
do symulowania drugiego -- kazdy z nich ma optymalny
zakres zastosowan.
Pozdrawiam
Piotr Wyderski
Krzysztof Urbanski
Guest
Sat Nov 06, 2004 8:18 pm
Piotr Wyderski napisał(a):
Quote:
extern "C" sygnatura_funkcji();
Jesli nazwa funkcji asemblerowej jest "dziwna", to mozna
sobie jeszcze pomoc podajac pelna nazwe za pomoca
__attribute__((__allias__)). Najlepiej jesli funkcje nie
biora parametrow i nie zwracaja wynikow; w przeciwnym
razie musisz sie zapoznac z tzw. konwencjami wywolania.
Tylko pamietaj, ze wstawka to cos innego niz zewnetrzna
funkcja, wiec staraj sie nie naduzywac jednego mechanizmu
do symulowania drugiego -- kazdy z nich ma optymalny
zakres zastosowan.
Pozdrawiam
Piotr Wyderski
Dzieki. Pokombinuje. Moze cos wkoncu z tego wyjdzie.
--
Pozdrawiam
Krzysztof Urbanski
krzysztof-u@[usun_to]wp.pl
Jurek Szczesiul
Guest
Sat Nov 06, 2004 8:40 pm
Sat, 06 Nov 2004 19:02:18 +0100, na pl.misc.elektronika, Krzysztof Urbanski
napisał(a):
Quote:
Moze jest jakis sposob zeby wywolywac funkcje napisane w calosci w asm
znajdujace sie w innych plikach ?
Deklarujesz w pliku asemblerowym .s funkcję jako globalną, w pliku .c jako
zewnętrzną (extern) i normalnie wywołujesz. Sprawa jest prosta dla funkcji
void, np. przykład z opóźnieniem może wyglądać tak :
<>
..global MyDelay
.section .text,"ax",@progbits
.type MyDelay,@function
MyDelay:
nop
nop
nop
ret
.size MyDelay, .-MyDelay
</>
- w deklaracjach pliku .c zapisujemy
extern void MyDelay(void);
a potem sobie z miarę potrzeb wywołujemy MyDelay();
W momencie gdy trzeba przekazać argumenty do funkcji i zwrócić wartość
rzeczy się oczywiście nieco komplikują. Ale i tak IMHO oddzielne pliki asm
są dużo bardziej przyjazne i czytelne niż barokowa składnia wstawek

)
Chociaż nie zawsze się to da tak całkiem zastąpić - tutaj wstawka realizuje
3 nopy; wywołanie funkcji to 3 nopy + rcall + ret a więc dużo więcej.
--
Pozdrowienia
Jurek Szczesiul
Wojtek Kaniewski
Guest
Mon Nov 08, 2004 8:54 pm
Krzysztof Urbanski wrote:
Quote:
Niedawno zaczalem zabawe z AVRami. Napisalem sobie petle opoznien w
asemblerze pod AVRStudio. Teraz zabralem sie za avrgcc i chcialbym
funkcje opoznien napisac jako wstawki asemblerowe. (...)
może to niedokładnie to, o co Ci chodzi, ale avr-libc zawiera już
większość kodu niezbędnego do opóźnień w <avr/delay.h>. dodaj zależności
od zegara w #define i gotowe.
w.
Krzysztof Urbanski
Guest
Tue Nov 09, 2004 9:24 pm
Napisalem cos takiego:
Plik "delay.s" w asemblerze:
___________________________________________________________________
;Generowanie opoznien
;Dane w jednostkach czasu podane dla rezonatora 11,0592 MHz
;Krzysztof Urbanski
;Slupsk 8.11.2004
;Opoznienie x*1us (dokladnie 0,994646...us) czyli x*11 cykli
;x umiescic w rejestrze r24
;orientacyjnie przy ustawieniu: 1us uzyskuje sie czas 1,625us
;i odpowiednio:
;2us - 2,62us
;3us - 3,615us
;10us - 10,57us
;100us - 100us
..global waitus
waitus:
cpi r24,1
breq koniec_waitus
dec r24
push r24 ;wytracanie czasu
pop r24 ;wytracanie czasu
nop
nop
rjmp waitus
koniec_waitus:
nop
ret
;Opoznienie (x*1ms)+0,994646...us czyli (x*11059 cykli)+15 cykle
;x umiescic w rejestrze r24
;uzywa rejestru r17
;jego zawartosc jest odtwarzana przed powrotem z podprogramu
..global waitms
waitms:
push r17 ;przechowanie r17 na stosie
mov r17,r24
start_waitms:
cpi r17,0
breq koniec_waitms
dec r17
ldi r24,200
rcall waitus
ldi r24,200
rcall waitus
ldi r24,200
rcall waitus
ldi r24,200
rcall waitus
ldi r24,203
rcall waitus
nop
rjmp start_waitms
koniec_waitms:
pop r17 ;odtworzenie r17 ze stosu
ret
;Opoznienie (x*1s)+0,994646...us czyli (x*11059200 cykli)+15 cykli
;x umiescic w rejestrze r24
;uzywa rejestru r17 i r18
;ich zawartosc jest odtwarzana przed powrotem z podprogramu
..global waits
waits:
push r18 ;przechowanie r18 na stosie
mov r18,r24
start_waits:
cpi r18,0
breq koniec_waits
dec r18
ldi r24,250
rcall waitms
ldi r24,250
rcall waitms
ldi r24,250
rcall waitms
ldi r24,249
rcall waitms
ldi r24,250
rcall waitus
ldi r24,254
rcall waitus
ldi r24,255
rcall waitus
ldi r24,255
rcall waitus
push r24 ;wytracanie czasu
pop r24 ;wytracanie czasu
push r24 ;wytracanie czasu
pop r24 ;wytracanie czasu
rjmp start_waits
koniec_waits:
pop r18 ;odtworzenie r18 ze stosu
ret
..end
__________________________________________________________________
Plik "main.c" w C uzywajacy opoznien:
#include <avr\io.h>
#define led 7 //definicja bitu portu dla LED
#define wy 6 //definicja bitu portu dla wyjscia
extern void waitus(unsigned char); //argument przekazywany jest przez
//rejestr r24
extern void waitms(unsigned char);
extern void waits(unsigned char);
int main(void) //program główny
{
PORTD=0xff; //jedynki na PORTD
DDRD=0xff; //PORTD wyjscia
while(1) {
sbi(PORTD,led);
sbi(PORTD,wy);
waits(1);
cbi(PORTD,led);
cbi(PORTD,wy);
waits(1);
}
}
_________________________________________________________________
Dziala bardzo dobrze i dokladnie, moze komus sie przyda.
Dzieki za odpowiedzi.
--
Pozdrawiam
Krzysztof Urbanski
krzysztof-u@[usun_to]wp.pl