AVR-GCC problem z opóźnieniem

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
yakuza
-
Posty: 38
Rejestracja: 10 sty 2006, 12:59
Kontakt:

AVR-GCC problem z opóźnieniem

Post autor: yakuza » 14 sie 2007, 10:39

Witam!

Przerabiam kurs AVR-GCC z Elektroniki dla Wszystkich. jestem już w 5 części. Jest tam kod odpowiedzialny za opóźnienia:

Kod: Zaznacz cały

#define delayus8(t)\
	{asm volatile( \
		"delayus8_loop%=: \n\t"\
			"nop \n\t"\
			"dec %[ticks] \n\t"\
			"brne delayus8_loop%= \n\t"\
	: :[ticks]"r"(t) );}
	// DEC - 1 cykl, BRNE 2 cykle, + 1xnop. Zegar 4MHz

void delay100us8(uint8_t t)
{
	while(t>0)
	{
		delayus8(100); 
		--t; 
	}
}
Ponieważ ja używam kwarcu 8 MHz to zmieniłem trochę makro delayus8():

Kod: Zaznacz cały

#define delayus8(t)\
	{asm volatile( \
		"delayus8_loop%=: \n\t"\
			"nop \n\t"\
			"nop \n\t"\
			"nop \n\t"\
			"nop \n\t"\
			"nop \n\t"\
			"dec %[ticks] \n\t"\
			"brne delayus8_loop%= \n\t"\
	: :[ticks]"r"(t) );}
	// DEC - 1 cykl, BRNE 2 cykle, + 5xnop. Zegar 8MHz

void delay100us8(uint8_t t)
{
	while(t>0)
	{
		delayus8(100); 
		--t; 
	}
}
Wg symulatora AVR Studio makro delayus8() działa dobrze, niestety funkcja delay100us8() daje dobre opóźnienie tylko, gdy argumentem jest 1. Dla 2 opóźnienie wynosi 358 us, a powinno być ok 200us.

Już nie mam pomysłu jak rozwiązać ten problem.

Pozdrawiam Yakuza
Ostatnio zmieniony 14 sie 2007, 14:32 przez yakuza, łącznie zmieniany 1 raz.

ZbeeGin

Post autor: ZbeeGin » 14 sie 2007, 12:02

A jaką optymalizację kodu masz włączoną?

yakuza
-
Posty: 38
Rejestracja: 10 sty 2006, 12:59
Kontakt:

Post autor: yakuza » 14 sie 2007, 15:28

Chodzi oto co jest w pliku makefile?
Jest ustawiona optymalizacja rozmiaru kodu wynikowego.

Pozdrawiam Yakuza

Edit:
Zmieniłem trochę program żeby robił 10 (a nie 100) "okrążeń" w makrze

Kod: Zaznacz cały

void delay100us8(uint8_t t)
{
	while(t>0)
	{
		delayus8(10); 
		--t; 
	}
}
i sprawdziłem jak to wyglada w asemblerze:

Kod: Zaznacz cały

35:       		delayus8(10); 
+0000004B:   0000        NOP                      No operation
+0000004C:   0000        NOP                      No operation
+0000004D:   0000        NOP                      No operation
+0000004E:   0000        NOP                      No operation
+0000004F:   0000        NOP                      No operation
+00000050:   952A        DEC     R18              Decrement
+00000051:   F7C9        BRNE    PC-0x06          Branch if not equal
+00000052:   5081        SUBI    R24,0x01         Subtract immediate
+00000053:   F7B9        BRNE    PC-0x08          Branch if not equal
+00000054:   9508        RET                      Subroutine return
W rejestrze R18 jest zapisane ile zostało "okrążeń" w makrze delayus8(), a w R24 ilość "okrążeń" pętli while. Po wykonaniu 10-ciu loop -ów w makrze, wartość rejestru R18 wynosi 0. Gdy w kolejnym loop -ie pętli while program będzie wykonywać delayus8(), to przy operacji DEC R18, rejestr będzie mieć wartość 255 (0 - 1 = 255), czyli makro delayus8 wykona 255 pętli. Więc wiem, co jest nie tak, ale nie umiem tego naprawić.

Awatar użytkownika
Koppel
Użytkownik
Posty: 500
Rejestracja: 24 lip 2005, 18:05
Lokalizacja: Gliwice

Post autor: Koppel » 14 sie 2007, 16:02

Sprawa była już poruszana na forum.
Poprawa kodu opóźnienia znajduje się w ostatniej części kursu.

Oryginalny kod w żaden sposób nie informuje kompilatora, że zawartość rejestru przekazującego wartość opóźnienia jest tracona. W takim przypadku, przy wykonywaniu większej ilości pętli ustawiany jest on tylko raz a w następnych przebiegach liczenie zaczyna się od 0 (256 cykli).

Poprawny kod dostępny też na stronie https://elportal.pl/n0017

yakuza
-
Posty: 38
Rejestracja: 10 sty 2006, 12:59
Kontakt:

Post autor: yakuza » 14 sie 2007, 16:25

Dzięki za pomoc :mrgreen: Sorry, ale nie znalazłem wcześniej odpowiedzi na ten problem :oops:

Pozdrawiam Yakuza

Awatar użytkownika
Koppel
Użytkownik
Posty: 500
Rejestracja: 24 lip 2005, 18:05
Lokalizacja: Gliwice

Post autor: Koppel » 14 sie 2007, 18:18

yakuza pisze:Dzięki za pomoc :mrgreen: Sorry, ale nie znalazłem wcześniej odpowiedzi na ten problem :oops:

Pozdrawiam Yakuza
No w tym przypadku to głównie mój błąd. Miałem opisać go jeszcze dodatkowo na stronie.... Wszystko ten brak czasu :|
Ale najważniejsze, że sprawa się wyjaśniła :)

Pozdrawiam
Koppel

ODPOWIEDZ