RTV forum PL | NewsGroups PL

Jak naprawić problem z miganiem diodą na ATmega z użyciem avr-gcc i C?

avr i C - kto nie rozumie: kompilator, procesor czy ja?

NOWY TEMAT

elektroda NewsGroups Forum Index - Elektronika Polska - Jak naprawić problem z miganiem diodą na ATmega z użyciem avr-gcc i C?

Goto page 1, 2  Next

Jakub Rakus
Guest

Sun Jan 06, 2013 3:15 pm   



Witajcie,

Ostatnie moje problemy (tu na grupie poruszane) z obsługą uarta na
atmelkach stały się moim gwoździem do trumny bascoma i w końcu się
zawziąłem na C, choć zabierałem się do tego już od roku jak pies do
jeża. No to na początek, standardowo pomrugamy diodą. Ot taki programik:

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRD = 0xFF;
PORTD = 0x00;
while(1)
{
PORTD ^= _BV(0);
_delay_ms(500);
}
}

I zonk, na porcie ciągle stan wysoki. Podejrzałem plik .lss i niby
wszystko ok, jak patrzę na instrukcję asemblera to powinno działać:

00000038 <main>:
38: 8f ef ldi r24, 0xFF
3a: 81 bb out 0x11, r24
3c: 12 ba out 0x12, r1
3e: 91 e0 ldi r25, 0x01
40: 82 b3 in r24, 0x12
42: 89 27 eor r24, r25
44: 82 bb out 0x12, r24
46: ef ef ldi r30, 0xFF
48: ff e3 ldi r31, 0x3F
4a: 31 97 sbiw r30, 0x01
4c: f1 f7 brne .-4
4e: 00 c0 rjmp .+0
50: f7 cf rjmp .-18

Ale niestety nie działa, stan na porcie zmienia się bez opóźnienia. A
teraz ciekawostka, zamiast wykorzystywać funkcję _delay_ms wstawiłem swoją:

void delay(void)
{
uint16_t i;
for (i=0;i<15000;i++);
}

Patrzę na plik .lss, a tu:

00000038 <delay>:
38: 88 e9 ldi r24, 0x98
3a: 9a e3 ldi r25, 0x3A
3c: 01 97 sbiw r24, 0x01
3e: f1 f7 brne .-4
40: 08 95 ret
00000042 <main>:
42: 8f ef ldi r24, 0xFF
44: 81 bb out 0x11, r24
46: 12 ba out 0x12, r1
48: 91 e0 ldi r25, 0x01
4a: 82 b3 in r24, 0x12
4c: 89 27 eor r24, r25
4e: 82 bb out 0x12, r24
50: fc cf rjmp .-8

Wychodzi na to, że po przełączeniu bitu PD0 w ogóle nie wywołuje funkcji
delay() - no i port tak właśnie się zachowuje, w kółko się przełącza.

Obstawiam opcję, że ja czegoś nie rozumie, ale może ktoś mnie oświeci.

--
Pozdrawiam
Jakub Rakus

Marek
Guest

Sun Jan 06, 2013 3:26 pm   



On Sun, 06 Jan 2013 15:15:46 +0100, Jakub Rakus <szczur01@op.pl>
wrote:
Quote:
Wychodzi na to, że po przełączeniu bitu PD0 w ogóle nie wywołuje
funkcji
delay() - no i port tak właśnie się zachowuje, w kółko się
przełącza.


Nie użyłeś volatile przy deklaracji zmiennej "i" w funkcji delay(),
"i" nie jest nigdzie wykorzystane dalej w kodzie funkcji więc
optymalizator wywalił cały for, jak nie potrzebny for to i cała
funkcja delay()...

--
Marek

Grzegorz Niemirowski
Guest

Sun Jan 06, 2013 3:29 pm   



Jakub Rakus <szczur01@op.pl> napisał(a):
Quote:
Witajcie,
Ostatnie moje problemy (tu na grupie poruszane) z obsługą uarta na
atmelkach stały się moim gwoździem do trumny bascoma i w końcu się
zawziąłem na C, choć zabierałem się do tego już od roku jak pies do jeża.

A problem był po stronie Bascoma czy niedopracowanego algorytmu?

Quote:
No to na początek, standardowo pomrugamy diodą. Ot taki programik:
#define F_CPU 16000000UL
#include <avr/io.h
#include <util/delay.h
int main(void)
{
DDRD = 0xFF;
PORTD = 0x00;
while(1)
{
PORTD ^= _BV(0);
_delay_ms(500);
}
}
I zonk, na porcie ciągle stan wysoki. Podejrzałem plik .lss i niby
wszystko ok, jak patrzę na instrukcję asemblera to powinno działać:
00000038 <main>:
38: 8f ef ldi r24, 0xFF
3a: 81 bb out 0x11, r24
3c: 12 ba out 0x12, r1
3e: 91 e0 ldi r25, 0x01
40: 82 b3 in r24, 0x12
42: 89 27 eor r24, r25
44: 82 bb out 0x12, r24
46: ef ef ldi r30, 0xFF
48: ff e3 ldi r31, 0x3F
4a: 31 97 sbiw r30, 0x01
4c: f1 f7 brne .-4
4e: 00 c0 rjmp .+0
50: f7 cf rjmp .-18
Ale niestety nie działa, stan na porcie zmienia się bez opóźnienia. A
teraz ciekawostka, zamiast wykorzystywać funkcję _delay_ms wstawiłem
swoją:
void delay(void)
{
uint16_t i;
for (i=0;i<15000;i++);
}
Patrzę na plik .lss, a tu:
00000038 <delay>:
38: 88 e9 ldi r24, 0x98
3a: 9a e3 ldi r25, 0x3A
3c: 01 97 sbiw r24, 0x01
3e: f1 f7 brne .-4
40: 08 95 ret
00000042 <main>:
42: 8f ef ldi r24, 0xFF
44: 81 bb out 0x11, r24
46: 12 ba out 0x12, r1
48: 91 e0 ldi r25, 0x01
4a: 82 b3 in r24, 0x12
4c: 89 27 eor r24, r25
4e: 82 bb out 0x12, r24
50: fc cf rjmp .-8
Wychodzi na to, że po przełączeniu bitu PD0 w ogóle nie wywołuje funkcji
delay() - no i port tak właśnie się zachowuje, w kółko się przełącza.
Obstawiam opcję, że ja czegoś nie rozumie, ale może ktoś mnie oświeci.

Ustawiłeś optymalizacje zgodnie z dokumentacją?
Którego kompilatora używasz?

--
Grzegorz Niemirowski
http://www.grzegorz.net/
OE PowerTool i Outlook Express: http://www.grzegorz.net/oe/
Uptime: 0 days, 1 hours, 26 minutes and 32 seconds

Jakub Rakus
Guest

Sun Jan 06, 2013 3:45 pm   



W dniu 06.01.2013 15:26, Marek pisze:

Quote:
Nie użyłeś volatile przy deklaracji zmiennej "i" w funkcji delay(), "i"
nie jest nigdzie wykorzystane dalej w kodzie funkcji więc optymalizator
wywalił cały for, jak nie potrzebny for to i cała funkcja delay()...

Ooo, no to jest racja, nie pomyślałem. Faktycznie, dodaję volatile,
wtedy śmiga. Podziękował!
Ale nadal pozostaje problem nie działającej funkcji _delay_ms().

--
Pozdrawiam
Jakub Rakus

Jakub Rakus
Guest

Sun Jan 06, 2013 3:57 pm   



W dniu 06.01.2013 15:29, Grzegorz Niemirowski pisze:
Quote:

A problem był po stronie Bascoma czy niedopracowanego algorytmu?

Problem polegał na tym, że pomimo wielu prób nie doszedłem do tego jak

stworzyć poprawnie działający algorytm pisząc go tylko w bascomie, nie
angażując w to asemblera, a nie miałem na to ochoty Wink - poza tym po
skompilowaniu miałem i tak już ogromny program (3kB!), a w planie
jeszcze kilka funkcjonalności, więc i tak bym doszedł do granicy
możliwości darmowego bascoma.
Quote:

Ustawiłeś optymalizacje zgodnie z dokumentacją?
Którego kompilatora używasz?

Korzystam z code::blocks i avr-gcc w wersji 4.5.3. Ustawiam

optymalizację na -O. Co ciekawe, gdy wyłączę optymalizację w ogóle,
oczywiście mam ostrzeżenie, że funkcje z delay.h będą działać
niepoprawnie, kompiluje się, program wynikowy jest ogromny, ale... działa.

--
Pozdrawiam
Jakub Rakus

Marek
Guest

Sun Jan 06, 2013 4:01 pm   



On Sun, 06 Jan 2013 15:45:11 +0100, Jakub Rakus <szczur01@op.pl>
wrote:
Quote:
Ale nadal pozostaje problem nie działającej funkcji _delay_ms().

Zgaduje teraz (nie znam się na avr), czy czasem nie potrzeba
wcześniej wywolac jakaś funkcję konfigurujaca bibliotekę wszystkich
funkcji delay? Skąd delay wie jaka jest aktualna częstotliwość
zegara?

--
Marek

Jakub Rakus
Guest

Sun Jan 06, 2013 4:09 pm   



W dniu 06.01.2013 16:01, Marek pisze:
Quote:
On Sun, 06 Jan 2013 15:45:11 +0100, Jakub Rakus <szczur01@op.pl> wrote:
Ale nadal pozostaje problem nie działającej funkcji _delay_ms().

Zgaduje teraz (nie znam się na avr), czy czasem nie potrzeba wcześniej
wywolac jakaś funkcję konfigurujaca bibliotekę wszystkich funkcji delay?
Skąd delay wie jaka jest aktualna częstotliwość zegara?


Zgodnie z tym co napisano na początku delay.h wystarczająca jest
linijka, którą mam na początku kodu:

#define F_CPU 16000000UL

A nawet gdyby jej nie było to przyjmie sobie domyślną wartość F_CPU
1000000UL.

--
Pozdrawiam
Jakub Rakus

Grzegorz Niemirowski
Guest

Sun Jan 06, 2013 4:58 pm   



Jakub Rakus <szczur01@op.pl> napisał(a):
Quote:
Korzystam z code::blocks i avr-gcc w wersji 4.5.3. Ustawiam optymalizację
na -O. Co ciekawe, gdy wyłączę optymalizację w ogóle, oczywiście mam
ostrzeżenie, że funkcje z delay.h będą działać niepoprawnie, kompiluje
się, program wynikowy jest ogromny, ale... działa.

Nie wiem, co u Ciebie dokładnie oznacza -O, u mnie jest to -O1. Twój program
działa bez żadnego problemu u mnie na ATmega32 (może kompilujesz na zły
procesor). Używam Atmel Studio 6 (
AVR/GNU C Compiler : (AVR_8_bit_GNU_Toolchain_3.4.0_663) 4.6.2)
Poza tym w pierwszym poście piszesz: "I zonk, na porcie ciągle stan wysoki."
z czego wynika, że u Ciebie w ogóle nie wykonuje się pętla while.
Mój lss:
00000092 <main>:

Jakub Rakus
Guest

Sun Jan 06, 2013 5:28 pm   



W dniu 06.01.2013 16:58, Grzegorz Niemirowski pisze:

Quote:
Nie wiem, co u Ciebie dokładnie oznacza -O, u mnie jest to -O1.
Zjadła się jedynka, też mam -O1.


Quote:
Poza tym w pierwszym poście piszesz: "I zonk, na porcie ciągle stan
wysoki." z czego wynika, że u Ciebie w ogóle nie wykonuje się pętla while.
Zasugerowałem się tym, że leda mi ciągle świeci, ale faktycznie pętla

się wykonuje - tylko, że cholernie szybko...

Quote:
//round up by default
__ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
#endif
__builtin_avr_delay_cycles(__ticks_dc);
a0: 2f ef ldi r18, 0xFF ; 255
a2: 39 e6 ldi r19, 0x69 ; 105
a4: 48 e1 ldi r20, 0x18 ; 24
a6: 21 50 subi r18, 0x01 ; 1
a8: 30 40 sbci r19, 0x00 ; 0
aa: 40 40 sbci r20, 0x00 ; 0
ac: e1 f7 brne .-8 ; 0xa6 <main+0x14
ae: 00 c0 rjmp .+0 ; 0xb0 <main+0x1e

O widzisz tu właśnie jest rozbieżność - u Ciebie jak widzę działa to
dokładnie tak jak opisane jest to na początku delay.h. U mnie
_HAS_DELAY_CYCLES ma wartość 1, więc teoretycznie także powinna zostać
wywołana funkcja _builtin_avr_delay_cycles, a z jakiegoś powodu tak się
nie dzieje.

--
Pozdrawiam
Jakub Rakus

Grzegorz Niemirowski
Guest

Sun Jan 06, 2013 5:46 pm   



Jakub Rakus <szczur01@op.pl> napisał(a):
Quote:
O widzisz tu właśnie jest rozbieżność - u Ciebie jak widzę działa to
dokładnie tak jak opisane jest to na początku delay.h. U mnie
_HAS_DELAY_CYCLES ma wartość 1, więc teoretycznie także powinna zostać
wywołana funkcja _builtin_avr_delay_cycles, a z jakiegoś powodu tak się
nie dzieje.

A czy ten Twój toolchain ma w ogóle tę funkcję? I dlaczego użwasz akurat
tego toolchaina a nie np. Atmel Studio 6 albo WinAVR?

--
Grzegorz Niemirowski
http://www.grzegorz.net/
OE PowerTool i Outlook Express: http://www.grzegorz.net/oe/
Uptime: 0 days, 0 hours, 57 minutes and 50 seconds

Jakub Rakus
Guest

Sun Jan 06, 2013 6:13 pm   



W dniu 06.01.2013 17:46, Grzegorz Niemirowski pisze:

Quote:
A czy ten Twój toolchain ma w ogóle tę funkcję? I dlaczego użwasz akurat
tego toolchaina a nie np. Atmel Studio 6 albo WinAVR?

Ale ja to wszystko robię pod linuxem. Więc podejrzewam właśnie brak owej
funkcji.

--
Pozdrawiam
Jakub Rakus

Grzegorz Niemirowski
Guest

Sun Jan 06, 2013 6:56 pm   



Jakub Rakus <szczur01@op.pl> napisał(a):
Quote:
Ale ja to wszystko robię pod linuxem. Więc podejrzewam właśnie brak owej
funkcji.

Też mi się wydaje, że jej tam nie ma. Ma moim Ubuntu jest tak samo jak u
Ciebie. Dlatego najprościej będzie zainstalować sobie Atmel Studio na
Windowsie. Chyba, że jest jakiś prosty patch na avt-libc, ale nie znalazłem.

--
Grzegorz Niemirowski
http://www.grzegorz.net/
OE PowerTool i Outlook Express: http://www.grzegorz.net/oe/
Uptime: 0 days, 2 hours, 4 minutes and 54 seconds

Jakub Rakus
Guest

Sun Jan 06, 2013 8:48 pm   



W dniu 06.01.2013 18:56, Grzegorz Niemirowski pisze:

Quote:
Też mi się wydaje, że jej tam nie ma. Ma moim Ubuntu jest tak samo jak u
Ciebie. Dlatego najprościej będzie zainstalować sobie Atmel Studio na
Windowsie. Chyba, że jest jakiś prosty patch na avt-libc, ale nie
znalazłem.

Windows jest feee, nie chce go Razz Ale znalazłem przyczynę i rozwiązanie
problemu, otóż problemem jest położenie plików nagłówkowych. Domyślnie
kompilator gcc-avr w ich poszukiwaniu przeszukuje katalog /usr/include a
tam niestety wszystkiego nie ma, wystarczy w ustawieniach kompilatora
zmienić mu ścieżkę na /usr/lib/avr/include i nagle wszystko zaczyna
działać jak należy.

--
Pozdrawiam
Jakub Rakus

Atlantis
Guest

Sun Jan 06, 2013 10:15 pm   



W dniu 2013-01-06 16:09, Jakub Rakus pisze:

Quote:
A nawet gdyby jej nie było to przyjmie sobie domyślną wartość F_CPU
1000000UL.

Chyba, że ustawimy inną w makefile.

Adam Wysocki
Guest

Tue Jan 08, 2013 12:15 pm   



Jakub Rakus <szczur01@op.pl> wrote:

Quote:
#define F_CPU 16000000UL
_delay_ms(500);

Za dużo.

http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

The maximal possible delay is 262.14 ms / F_CPU in MHz.

Daj:

for (int i(0); i < 50; ++i)
_delay_ms(10);

--
Gof
http://www.chmurka.net/

Goto page 1, 2  Next

elektroda NewsGroups Forum Index - Elektronika Polska - Jak naprawić problem z miganiem diodą na ATmega z użyciem avr-gcc i C?

NOWY TEMAT

Regulamin - Zasady uzytkowania Polityka prywatnosci Kontakt RTV map News map