wwojtek napisał(a):
1. Zauważyłeś jakąś różnicę po dodaniu atrybutu "OS_main" do main? W kilku projektach sprawdzałem co daje OS_main (ewentualnie noreturn) dodane do main i nigdy nie było różnicy w generowanym kodzie ;/
Owszem jest różnica. Z tym atrybutem w prologu main nie są zapisywane rejestry "call-saved", czyli r2-r17, r28, r29. Pewnie jak w main wstawisz same wywołania funkcji i program nie ruszy tych rejestrów to nie zauważysz różnicy (kompilator ich nie zachowa, bo po co).
Mam tu jakiś programik pod ręką - różnica w progmem po skompilowaniu: 4 bajty (bez atrybutu jest więcej). Co gorsze na zachowanie tych rejestrów niepotrzebnie zużywany jest RAM. Początek funkcji main bez OS_main:
język asm
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Nie wiem po co instrukcje rcall .+0, które nic nie robią choć zużywają 6 bajtów RAMu.
Z OS_main:
język asm
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
wwojtek napisał(a):
2. rjmp .+0 vs nop - jest jakaś praktyczna różnica?
I jak to się ma np. w ARM? Z tego co pamiętam to, w Cortex'ach nop może zaginąć gdzieś w pipeline'ie i nie można na nim polegać w 100% jeśli chodzi o opóźnienia. Jakoś nigdy nie pomyślałem, aby zamienić nop'a na coś inszego acz równie nie-produktywnego
Zarówno rjmp jak i nop zajmują we flash jedno słowo, jednak rjmp trwa 2 takty, a nop jeden. A więc mamy 200% normy z jednej instrukcji
Z innych ciekawych instrukcji opóźniających, które niedawno stosowałem: para rcall/ret. Trochę kłopotliwa na co dzień, ale w stawce asemblerowej można wykorzystać. Dwa słowa i 7 (lub 9 w prockach z większą pamięcią) taktów - 350% normy. A zważywszy, że w podprogramach instrukcję ret już i tak mamy to i 700% normy
Czy można polegać? Jeśli tylko kompilator instrukcji nie usunie (a po to dajemy volatile, żeby nie usunął) to na 100% można. To nie ARM. Nie, żebym sie jakoś szczególnie znał na ARMach (czy choćby tylko odrobinę
), ale słyszałem że AVR są "real time" a ARM nie.
wwojtek napisał(a):
3. W ramach optymalizacji można by chyba zrezygnować z rand_flag i przy starcie programu wpisywać do rand_value niemożliwą wartość (>5) co byłoby wyznacznikiem że jeszcze nie było losowania
Można. Po to nawet utworzyłem stałą NOT_YET ale nie lubię takich zlepków, więc dodałem flagę (stała pozostała, choć trochę nie wiadomo po co
).
wwojtek napisał(a):
4. "MCUSR = 0; //Niewyzerowana flaga WDRF nie pozwoli na wyłączenie resetu" - chyba coś zgubiłem ;/ jakiego resetu?
Trybu reset watchdoga. Jeżeli nastąpił reset zainicjowany przez watchdoga, to procek wstaje z ustawioną flagą WDRF i
aktywnym watchdogiem. Trzeba go wyłączyć, żeby nie bruździł. Ale wykonanie sekwencji wyłączającej (ustaw WDCE i WDE i w ciągu 4 taktów wyzeruj WDTCSR) z wciąż ustawioną flagą WDRF, nie odniesie skutku. Uprzednio trzeba go wyzerować.