avr-gcc i wstawki asemblerowe



Masz problem? Zapytaj na forum elektroda.pl

Poprzedni Następny
Wiadomość
Spis treści
From: Krzysztof Urbanski <krzysztof-u_at_nospam_[usun_to]wp.pl>
Subject: avr-gcc i wstawki asemblerowe
Date: Sat, 06 Nov 2004 19:02:18 +0100


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_at_nospam_[usun_to]wp.pl

Poprzedni Następny
Wiadomość
Spis treści
From: "Piotr Wyderski" <wyderskiREMOVE_at_nospam_ii.uni.wroc.pl>
Subject: Re: avr-gcc i wstawki asemblerowe
Date: Sat, 6 Nov 2004 20:20:30 +0100


Krzysztof Urbanski wrote:

asm volatile("nop");
asm volatile("nop");
asm volatile("nop");

Sprobuj to zrobic w jednym bloku volatile:

asm volatile("\tnop\n" \
"\tnop\n" \
"\tnop\n");

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.

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


Poprzedni Następny
Wiadomość
Spis treści
From: Krzysztof Urbanski <krzysztof-u_at_nospam_[usun_to]wp.pl>
Subject: Re: avr-gcc i wstawki asemblerowe
Date: Sat, 06 Nov 2004 21:18:26 +0100


Piotr Wyderski napisał(a):
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_at_nospam_[usun_to]wp.pl

Poprzedni Następny
Wiadomość
Spis treści
From: Jurek Szczesiul <jerzy.szczesiul_at_nospam_wycin.ep.com.pl>
Subject: Re: avr-gcc i wstawki asemblerowe
Date: Sat, 6 Nov 2004 21:40:41 +0100


Sat, 06 Nov 2004 19:02:18 +0100, na pl.misc.elektronika, Krzysztof Urbanski
napisał(a):

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",_at_nospam_progbits
.type MyDelay,_at_nospam_function
MyDelay:
nop
nop
nop
ret
.size MyDelay, .-MyDelay
</>

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

Poprzedni Następny
Wiadomość
Spis treści
From: Wojtek Kaniewski <wojtekka_at_nospam_SPAM.SPAM.SPAM>
Subject: Re: avr-gcc i wstawki asemblerowe
Date: Mon, 08 Nov 2004 21:54:30 +0100


Krzysztof Urbanski wrote:
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.

Poprzedni Następny
Wiadomość
Spis treści
From: Krzysztof Urbanski <krzysztof-u_at_nospam_[usun_to]wp.pl>
Subject: Re: avr-gcc i wstawki asemblerowe
Date: Tue, 09 Nov 2004 22:24:30 +0100


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_at_nospam_[usun_to]wp.pl