-
31. Data: 2011-02-11 12:22:23
Temat: Re: AVR ATmega, pomiar częstotliwości przebiegu, prośba o sprawdzenie kodu
Od: "Robbo" <y...@m...com>
>Zamiast tego posłuż się ATOMIC_BLOCK
Zrobiłem tak:
while (1) {
ATOMIC_BLOCK(ATOMIC_FORCEON) {
actualDurationLatch = actualDuration;
}
sprintf(s, "%d %ld ", i++, actualDurationLatch);
LCDwriteString(s);
}
W Makefile dałem -std=gnu99.
Efekt jest taki, że na wyświetlaczu widzę cały czas zwiększającą się wartość
zmiennej "i". Natomiast actualDurationLatch przyjmuje jakąś wartość i tak
już trwa -- nie reaguje na zmianę częstotliwości. Gdy wyrzucę ATOMIC_BLOCK,
to actualDurationLatch ożywa.
R.
-
32. Data: 2011-02-11 12:24:36
Temat: Re: AVR ATmega, pomiar częstotliwości przebiegu, prośba o sprawdzenie kodu
Od: Zbych <a...@o...pl>
W dniu 2011-02-11 12:05, Robbo pisze:
>> Jak już muszę użyć to często robię unię zmiennej volatile i bez
>> volatile. Dzięki czemu nie mam nadmiarowego kodu np. w przerwaniach.
>
> Gdybyś mógł wyjaśnić, co daje taka konstrukcja...?
W ogólności krótszy/szybszy kod. Użycie volatile to zakaz optymalizacji
dla kompilatora. Poniżej masz prosty przykład z odmierzaniem opóźnienia
przez przerwanie timera. Gdyby zmienna była volatile, to w przerwaniu
musiałbyś ją pobrać dwa razy.
union{
volatile uint8_t V;
uint8_t NV;
}aqq;
ISR(od_jakiegos_timera){
if (aqq.NV != 0) aqq.NV--;
}
main(){
aqq.V = 100;
while(aqq.V != 0);
}
-
33. Data: 2011-02-11 12:33:03
Temat: Re: AVR ATmega, pomiar częstotliwości przebiegu, prośba o sprawdzenie kodu
Od: Zbych <a...@o...pl>
W dniu 2011-02-11 13:22, Robbo pisze:
>> Zamiast tego posłuż się ATOMIC_BLOCK
>
>
> Zrobiłem tak:
>
> while (1) {
> ATOMIC_BLOCK(ATOMIC_FORCEON) {
> actualDurationLatch = actualDuration;
> }
>
> sprintf(s, "%d %ld ", i++, actualDurationLatch);
> LCDwriteString(s);
> }
>
> W Makefile dałem -std=gnu99.
>
> Efekt jest taki, że na wyświetlaczu widzę cały czas zwiększającą się
> wartość zmiennej "i". Natomiast actualDurationLatch przyjmuje jakąś
> wartość i tak już trwa -- nie reaguje na zmianę częstotliwości. Gdy
> wyrzucę ATOMIC_BLOCK, to actualDurationLatch ożywa.
Dopisz do swojego programu dwie linie:
while (1) {
asm volatile(";ala ma kota - start"); //<----------------
ATOMIC_BLOCK(ATOMIC_FORCEON) {
actualDurationLatch = actualDuration;
}
asm volatile(";ala ma kota - stop"); //<----------------
sprintf(s, "%d %ld ", i++, actualDurationLatch);
LCDwriteString(s);
}
Skompiluj, otwórz plik *.lss, który zawiera program po deasemblacji,
poszukaj ciągu "ala ma kota" i porównaj czym wersja z ATOMIC różni się
od wersji bez ATOMIC.
-
34. Data: 2011-02-11 12:58:27
Temat: Re: AVR ATmega, pomiar częstotliwości przebiegu, prośba o sprawdzenie kodu
Od: "Robbo" <y...@m...com>
Dzięki za wyjaśnienie.
Sprawdziłem...
union{
volatile uint8_t V;
uint8_t NV;
}aqq;
ISR(od_jakiegos_timera){
if (aqq.NV != 0) aqq.NV--;
}
main(){
aqq.V = 100;
while(aqq.V != 0);
}
Daje kod dla ISR():
push r1
push r0
in r0, 0x3f
push r0
eor r1, r1
push r24
lds r24,0x0100
and r24, r24
breq .+6
subi r24, 0x01
sts 0x0100, r24
pop r24
pop r0
out 0x3f, r0
pop r0
pop r1
reti
----------------
Natomiast program:
volatile uint8_t V;
ISR(od_jakiegos_timera){
if (V != 0) V--;
}
main(){
V = 100;
while(V != 0);
}
Daje kod dla ISR():
push r1
push r0
in r0, 0x3f
push r0
eor r1, r1
push r24
lds r24,0x0100
and r24, r24
breq .+10
lds r24, 0x0100
subi r24, 0x01
sts 0x0100, r24
pop r24
pop r0
out 0x3f, r0
pop r0
pop r1
reti
---
Mam pytanie. Czy do tych "sztuczek" sam dochodziłeś, czy też mógłbyś polecić
jakieś książki/tutoriale dotyczące optymalizacji kodu dla mikrokontrolerów?
R.
-
35. Data: 2011-02-11 13:09:41
Temat: Re: AVR ATmega, pomiar częstotliwości przebiegu, prośba o sprawdzenie kodu
Od: "Robbo" <y...@m...com>
Z ATOMIC i bez ATOMIC wygląda tak samo:
lds r24, 0x052f
lds r25, 0x0530
lds r26, 0x0531
lds r27, 0x0532
sts 0x029e, r24
sts 0x029f, r25
sts 0x02a0, r26
sts 0x02a1, r27
Ale zauważyłem (patrząc w plik main.lst), że użycie ATOMIC spowodowało, iż
przed pętlą while (1) znalazło się iCliRetVal:
static __inline__ uint8_t __iCliRetVal(void)
{
cli();
while (1) {
asm volatile(";ala ma kota - start"); //<--------
ATOMIC_BLOCK(ATOMIC_FORCEON) {
actualDurationLatch = actualDuration;
...
R.