logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Różnice wielkości pliku po kompilacji AVR-GCC.

dziechu 05 Cze 2010 11:27 5466 47
  • #1 8157224
    dziechu
    Poziom 27  
    Witam. Od wielu lat programuję kontrolery w asemblerze. Ostatnio jednak z pewnych wzgledów praktycznych zacząłem używać języka C, no i zaczęły się dziać rzeczy poza moją kontrolą (czego zresztą spodziewałwm sie po C;) Mam zainstalowane AVR Studio 4, ostatnią wersję. Kilka tygodni temu doinstalowałem AVR-GCC. Problem polega na tym, że pliki wynikowe .hex, generowane dla tego samego wsadu przez AVR Studio i edytor AVR-GCC mają bardzo różne wielkości. Podobno AVR Studio korzysta z kompilatora GCC, a więc pliki powinny być podobne. Tymczasem, bez względu na ustawiony typ optymalizacji, z AVR Studio nie udało mi się otrzymać pliku .hex poniżej 8 kB, podczas gdy edytorem GCC otrzymuję poniżej 5 kB. Jedyna opcja jaka przychodzi mi do głowy, to stopień optymalizacji ustawiany w projekcie AVR Studio i pliku Makefile dla GCC. Gdzie może być ukryty problem? Dodam że czasem zdarza się sytuacja odwrotna - GCC generuje większy plik niż AVR Studio i nie są to różnice 5% ale 50% i więcej.
  • Pomocny post
    #2 8157955
    gaskoin
    Poziom 38  
    najlepiej to sprawdzic wylaczajac optymalizacje calkiem, i tu i tu i zobaczyc czy bedzie to samo, avr studio tez korzysta z kompilatora avr-gcc wiec roznic byc nie powinno
  • #3 8158306
    dziechu
    Poziom 27  
    są różnice cały czas, np. bez optymalizacji z AVR studio 14kB, z GCC 11kB. Ale zrobiłem coś innego - w opcjach projektu AVR Studio wyłączyłem wszystkie ustawienia przez funkcję 'użyj zewnętrznego pliku Makefile' i wskazałem plik makefile z GCC - teraz jest identycznie to samo. Skąd tak wielkie różnice ustawień AVR Studio i Makefile z GCC? Przy niby takich samych ustawieniach? Np. w obu wyłączona optymalizacja lub w obu optymalizacja na wielkość pliku (s w makefole i Os w AVR Studio) i różnice ok. 30%???
  • #4 8158534
    gaskoin
    Poziom 38  
    i tu i tu jest ustwaiony ten sam procesor ?
  • #6 8159721
    tmf
    VIP Zasłużony dla elektroda
    Optymalizacja -Ox to nie wszystkie optymalizacje jakie można zrobić. Nie ma bata - gdzieś musisz mieć różnice. Druga rzecz - nie patrz na wielkość hexa bo to o niczym nie świadczy, avrsize prawdę ci powie. Kolejna rzecz to biblioteki - może program nie jest linkowany z tymi samymi. Tu szczegolnie zwróć uwagę na libm i biblioteki związane z (s)printf.
  • #7 8159723
    beluosus
    Poziom 25  
    W logu w okienku "build" masz wypisane z jakimi dokładnie parametrami zostaje uruchomiony kompilator. To jest niemożliwe żeby program wynikowy miał różne rozmiary dla dokładnie tych samych parametrów tego samego kompilatora. Co innego różne kompilatory, wtedy oczywiste jest, że każdy może dać zupełnie inny wynik.
  • #8 8159760
    gaskoin
    Poziom 38  
    własnie - czasami jest niewykorzystana biblioteka w include, i niektore kompilatory ja olewaja, a niektore ja kompiluja :) nie wiem od czego to zalezy i czy jest to normalne zjawisko
  • #9 8160223
    dziechu
    Poziom 27  
    Próbowałem wszystkie opcje optymalizacji, nie tylko Os (O0, O1, O2, O3, Os). Przy żadnej AVR Studio nie schodzi poniżej 8 kB, podczas gdy GCC robi 5 kB. Patrzę głównie na wielkość pliku w informacji kompilatora - AVR size, czasem tylko na plik .hex. Biblioteki są dołączone tylko niezbędne, nie ma nic niepotrzebnego, są to tylko 3 biblioteki i bez jakiejkolwiek program by nie dzialał. Zresztą na ten pomysł też wpadłem i wszystko sprawdzałem. Co prawda w C dopiero zaczynam, ale w asemblerach programuje od bardzo wielu lat, więc mam taką 'ogólną orientację' w tych sprawach i głupotami bym Wam głowy nie zawracał. Dla mnie to także dziwna rzecz no i uciążliwa, bo wielkosć pliku hex jest dla mnie bardzo ważna. I tak nie wiem czy pomieszczę się w Mega32, choć widzę że Atmel wypuścił nowe procki, w tym Mega 644 z 64 kB pamieci flash ale tej samej obudowie i rozkładzie pinów jak 32. Jedyne co mogę zrobić to pokazać wam jakieś zrzuty ekranu, tylko napiszcie jakie. Być może jest jakaś 'pierdółka' której nie widzę, ale nic z tego co proponujecie. Dzięki za chęć pomocy:)

    Dodano po 8 [minuty]:

    Przy okazji mam jeszcze takie pytanie odnośnie biblioteki math.h - czy można w C jakoś tak zadeklarować dokładność operacji zmiennoprzecinkowych, żeby nie zabierały tyle miejsca? Dam przykład - urządzenie musi wyświetlić wynik w postaci logarytmicznej. Np. musi obliczyć log10 z 4000. Jeżeli zmienną wyniku zadeklaruję jako int. to otrzymuję wynik 3, czyli tylko część całkowitą, a potrzebuję 2 miejsca po przecinku (czyli w tym wypadku 3.60). Jeżeli zadeklaruję ją jako float. to wszystko mam pięknie obliczone, ale sama procedura obliczenia log10 zajmuje ponad 25 kB, a pewnie niepotrzebnie liczy z 8 miejsc po przecinku. Są na to jakieś sposoby?
  • #10 8160378
    tmf
    VIP Zasłużony dla elektroda
    Pokaż opcje projektu z AVR Studio - wszystkie, wklej linie wywołania gcc z twojego projektu makefile - to co ci się pojawia na ekranie przy kompilacji.
    Różnic wielkości przy tych samych opcjach być nie może, bo AVR Studio wywołuje gcc.
  • #11 8160799
    dziechu
    Poziom 27  
    Wywołuje GCC ale z innymi parametrami, przy czym nie potrafię ustawić żeby były takie same. W AVR Studio są dwie możliwości ustawienia parametrów - w okienku opcji projektu, lub też można włączyć zewnętrzny plik makefile, wtedy opcje AVR Studio są nieaktywne. Jest jeszcze jedna różnica - kiedy włączone są opcje AVR Studio, pliki zewnętrzne typu .c muszą być dołączone w opcjach projektu a nie instrukcją #include w pliku głównym (ineczej zgłasza błąd). W przypadku użycia zewnętrznego pliku makefile jest odwrotnie - pliki dodatkowe typu .c muszą być dołączone w pliku głównym instrukcją #include, a usunięte z plików dodatkowych AVR Studio. Choć są to te same pliki, to być może tu gdzieś coś źle robię? Ale co? Chyba kompilator nie może dołączyć i skompilować dwa razy tego samego pliku zewnętrznego, raczej zgłosiłby błąd... Zrzuty ekranu dołączę jak uzyskam dostęp do drugiego komputera, który skutecznie blokują mi dzieci grając w 4story;)

    Dodano po 12 [minuty]:

    Dla wyjaśnienia - poprzednio kompilowałem w AVR Studio i w tym edytorze z WinAVR. Teraz wszystko kompiluję w AVR Studio, tylko raz z ustawieniami projektu AVR Studio a raz z plikiem zewnętrznym Makefile, tym z którym kompilowałem w tatmtym edytorze. Różnice są dokładnie te same, czyli wynikają z różnic polecen dla kompilatora. Tylko dlaczego z Makefile mam 5 kB, a z opcjami AVR Studio 8kB lub większe...
  • #12 8160871
    gaskoin
    Poziom 38  
    dziechu napisał:

    Przy okazji mam jeszcze takie pytanie odnośnie biblioteki math.h - czy można w C jakoś tak zadeklarować dokładność operacji zmiennoprzecinkowych, żeby nie zabierały tyle miejsca? Dam przykład - urządzenie musi wyświetlić wynik w postaci logarytmicznej. Np. musi obliczyć log10 z 4000. Jeżeli zmienną wyniku zadeklaruję jako int. to otrzymuję wynik 3, czyli tylko część całkowitą, a potrzebuję 2 miejsca po przecinku (czyli w tym wypadku 3.60). Jeżeli zadeklaruję ją jako float. to wszystko mam pięknie obliczone, ale sama procedura obliczenia log10 zajmuje ponad 25 kB, a pewnie niepotrzebnie liczy z 8 miejsc po przecinku. Są na to jakieś sposoby?


    Mozesz sam sobie napisać obliczanie logarytmu z zadana dokladnoscia (czym mniejsza dokladnosc - tym szybciej liczy), chociazby wykorzystujac rozwiniecie funkcji w szereg taylora, ale mimo wszystko i tak to wszystko troche bedzie trwalo (bo tak samo jest zaimplementowana funkcja log w bibliotece math), jezeli mialoby liczyc tylko do np dwoch miejsc po przecinku to zamiast np 1.32 mozesz uzyskac 1.78
  • #13 8160957
    beluosus
    Poziom 25  
    dziechu napisał:
    Jest jeszcze jedna różnica - kiedy włączone są opcje AVR Studio, pliki zewnętrzne typu .c muszą być dołączone w opcjach projektu a nie instrukcją #include w pliku głównym (ineczej zgłasza błąd). W przypadku użycia zewnętrznego pliku makefile jest odwrotnie - pliki dodatkowe typu .c muszą być dołączone w pliku głównym instrukcją #include, a usunięte z plików dodatkowych AVR Studio.

    To jest oczywiste. Jeśli nie zdefiniujesz makefile to AVR Studio przejmuje jego rolę i musi znać zależności - stąd konieczność dodania plików do projektu. Makefile załatwia to na swój sposób.

    dziechu napisał:
    Chyba kompilator nie może dołączyć i skompilować dwa razy tego samego pliku zewnętrznego, raczej zgłosiłby błąd...

    Do zapobiegania podwójnych deklaracji używa się w plikach nagłówkowych takiej konstrukcji
    #ifndef _PLIK_H
    #define _PLIK_H
    
    // treść pliku plik.h
    
    #endif /* _PLIK_H */
  • #14 8160973
    PO.
    Poziom 20  
    No to mnie zmartwiłeś, używałem sobie dotąd w nieświadomości avr studio i za to płaciłem...

    Z #include to niemożliwe, wszystko inkluduję w głównym na standardowym makefile i co więcej, jak dodam jeszcze pliki do drzewka projektu, to zaczyna walić błędami bo ma podwójnie inkludowane i głupieje.

    Różnica wielkości samego pliku wsadu może wynikać z różnego pakowania zawartości - np 10 vs 20 bajtów i już dodatkowa zawartość robi różnicę :) . Więc nie posiłkuj się nigdy plikiem albo przynajlmniej sprawdź jak zapisuje i czy ma tyle samo linijek i takiej samej długości.
    Co do opcji kompilacji sam jestem ciekaw - może porównaj oba makefile?
  • #16 8161078
    markosik20
    Poziom 33  
    Zamieść z łaski swojej oba całe pliki makefile (ten zewnętrzny oraz tworzony automatycznie z AVRStudio).
  • #17 8161082
    tmf
    VIP Zasłużony dla elektroda
    dziechu napisał:
    Wywołuje GCC ale z innymi parametrami, przy czym nie potrafię ustawić żeby były takie same. W AVR Studio są dwie możliwości ustawienia parametrów - w okienku opcji projektu, lub też można włączyć zewnętrzny plik makefile, wtedy opcje AVR Studio są nieaktywne. Jest jeszcze jedna różnica - kiedy włączone są opcje AVR Studio, pliki zewnętrzne typu .c muszą być dołączone w opcjach projektu a nie instrukcją #include w pliku głównym (ineczej zgłasza błąd). W przypadku użycia zewnętrznego pliku makefile jest odwrotnie - pliki dodatkowe typu .c muszą być dołączone w pliku głównym instrukcją #include, a usunięte z plików dodatkowych AVR Studio.


    Nie potraktuj tego jako złośliwość, ale z tego co właśnie napisałeś wynika, że powinieneś najpierw poczytać jakąś książkę o c i coś o pisaniu makefile. Bo nie rozróżniasz pliku z deklaracjami (nagłówkowego) z plikiem z implementacją (źródłowego .c). Include służy wyłącznie do dołączania deklaracji funkcji (prototypów). Wszelkie pliki źródłowe muszą być dołączone w makefile jako osobne jednostki kompilacji, podobnie w AVR Studio, żeby mógł z tego wygrenerować prawidłowy makefile.
    Include nie służy do dołączania plików źródłowych.

    Co do logarytmów to poszukaj bibliotek operujących na formatach stałoprzecinkowych, powinno to działać znacznie szybciej. Ale obawiam się, że implementację logarytmu będziesz musiał zrobić sam. Z drugiej strony jeśli to ci od razu pochłonęło 25kB pamięci, to znaczy, że nie dołączyłeś libm i kompilator sam wygenerował (jak widać nieefektywnie) potrzebne funkcje.

    Dodano po 2 [minuty]:

    Co do opcji w AVR Studio to są one w zakładce Project Options->Custom Options. Zrób zrzut z tego okienka.
  • #18 8161136
    dziechu
    Poziom 27  
    Nie traktuje tego jako złośliwości, pisałem że zaczynam (w C pisze od tygodnia;). Ale wytłumacz jedno - w obu przypadkach optymalizacja ustawiona na wielkość pliku (s), oba programy działają prwidłowo, więc co ma być dołączone - jest, i chyba nie dwa razy. Dlaczego w jednym przypadku jest 8 kB a w drugim 5kB. Mógłbym zrozumieć różnice rzędu 5%, ale tu chyba zbyt wiele. Pliku Makefile nie piszę, wykorzystuję generator Makefile - zmieniam tylko ustawienia, a dokładnie rodzaj procesora, nazwa pliku głównego.

    Dodano po 1 [minuty]:

    Poza tym, gdyby odpowiednie pliki c nie były prawidłowo dołączone, to przecież kompilator zgłosi błąd trafiając na wywołanie funkcji w niedołączonym pliku???

    Dodano po 17 [minuty]:

    Różnice wielkości pliku po kompilacji AVR-GCC.
  • #19 8161232
    tmf
    VIP Zasłużony dla elektroda
    Jak na początku pisałem, jest tak dlatego, że -Os to nie jedyna opcja optymalizacji. Jest ich kilkadziesiąt i dodanie kolejnej może wpłynąć na kod. Tak spore różnice mogą też wynikać z innego poziomu inlinowania funkcji - znowu kolejna opcja kompilacji.
    Co do dołączania - include włączy ci też plik źródłowy, kompilator nie da żadnego ostrzeżenia, bo dla niego ważny jest tylko kod - plik nagłówkowy w końcu może także oprócz deklaracji prototypów, zawierać definicje funkcji. Tylko potem właśnie kończysz tak, że pojawiają się jakieś dziwne błędy. Także to, że kompilator nie generuje błędów to wcale nie znaczy, że ich nie ma.
  • #20 8161289
    dziechu
    Poziom 27  
    No ja nie mam pojęcia, dlatego pytam. Fakty są takie - oba pliki hex załadowane do procesora działają, więc raczej błędów kompilacji nie ma, braków kodu też nie. Jeżeli chodzi o ustawienia optymalizacji, to widze ich tylko kilka, przy czym optymalizacja s (size chyba) jest ukierunkowana na max. zmniejszenie kodu i tak działa - hex generowany z tą opcją jest najmniejszy, ale ma 8 kB, dlaczego nie 5 jak przy kompilacji z Makefile zewnętrznym?. Pewnie jakby ktoś z Was usiadł przy moim komputerze, to po 5min. wszystko było by jasne (prawdopodobnie).

    Dodano po 6 [minuty]:

    No i jeszcze jedno pytanie, odnośnie tej sytuacji ostatniego, dolnego obrazka z trzech - pliki zewnętrzne są dołączone po lewej jako Source Files. Dlaczego deklaracje funkcji #include tych plików są traktowane jako błąd? Jak widać obie są wyłączone komentarzem. A include raczej kojarzy mi się z dołączeniem a nie zadeklarowaniem.. już sam nie wiem.

    Dodano po 4 [minuty]:

    Może ktoś z Was, jeżeli używa AVR Studio, spróbuje u siebie na jakimś projekcie? Czy z ustawieniami AVR Studio i zewnętrznym Makefile dostanie podobne hexy?

    P.S. Wiedziałem że z tym C zacznie się czarna magia;) W asemblerze mogę sobie przeanalizować rozkaz po rozkazie, bo hex jest praktycznie wierny 1:1 temu co piszę. W C chyba nikt nie jest w stanie zrobić takiej analizy, poza najprostszymi programikami. Ale gotowych bibliotek w C jest mnóstwo, w asemblerze nic i każdy nowy wyświetlacz czy inne urządzenie to zabawa od 0.
  • Pomocny post
    #21 8161767
    markosik20
    Poziom 33  
    Wyślij mi maila z plikami i makefile'em. Skompiluje to u siebie w AVR Stduio, Eclipse+plugin oraz "na żywca"....porównamy :wink:.
  • #22 8162050
    tmf
    VIP Zasłużony dla elektroda
    Jak już pisałem są inne opcje, oprócz -Os, które powodują dalsze zmniejszenie kodu...
    Co do dołączania plików - najprościej sobie to wyobraź w ten sposób, że include powoduje, że w miejscu w którym jest nagle pojawia się cały plik, który includujesz - coś jakby copy/paste. Jeśli pliki są dodawane do makefile to są kompilowane oddzielnie jako oddzielne jednostki kompilacji. Makefile zawiera wtedy wywołania gcc z kolejnymi plikami. Taki makefile generuje też AVR Studio jeśli do projektu dołączysz kolejne pliki. Także sposób kompilacji w obu sytuacjach jest totalnie różny. Różne są też jego konsekwencje. Funkcje z oddzielnych jednostek kompilacji trafiają pod inaczej nazwane sekcje, co z kolei powoduje, że linker może nieużywane funkcje wyrzucić. To z kolei zmniejsza długość kodu (podobne zachowanie dla każdej funkcji można wymusić stosowną opcją). Ale są też inne konsekwencje - prywatne zmienne modułu (zadeklarowane jako static) nie są widoczne poza jednostką kompilacji. Jeśli w programie identyczne zmienne wystąpią wielokrotnie to nic się nie stanie. Jeśli jednak poszczególne pliki połączysz przez include to nagle pojawią się błędy o wielokrotnie zadeklarowanych etykietach itd.
    Co do analizy (debuggowania jak sądzę?) oczywiście, że możesz prześledzić program rozkaz po rozkazie - do tego celu służy okienko View->Disassembler, zobaczysz w trakcie sesji debuggera, że pokazuje ci linie kodu i instrukcje assemblera na które została przetłumaczona. Możesz sobie wtedy wykonywać linia po linii kod w C, albo instrukcja po instrukcji assemblera, albo jak tam sobie wymyślisz. Możesz też zobaczyć co wyprodukował kompilator przeglądając plik map i lss (o ile zaznaczyłeś opcje generowania tych plików).
  • #23 8162169
    dziechu
    Poziom 27  
    Ok, dzięki za informacje. Puki nie załapię całej filozofii, będę próbował różnych metod. Markosik - postaram sie jeszcze dziś wysłać te pliki, jak znowu uzyskam dostęp do drugiego komputera:) Wielkie dzięki jeszcze raz.

    Dodano po 37 [minuty]:

    Rozumiem tą część - jeżeli mam w pliku funkcje.c np. 10 różnych funkcji i dołączę ten plik przez #include funkcje.c, to kompilator dołączy mi wszystkie te funkcje do kodu, nawet jeżeli nie wszystkie są używane. To sprawdziłem. W takim razie jak dołączyć plik funkcje.c do projektu tak, aby kompilator dołączał kod tylko tych funkcji, które zostaną wywołane? Na razie robię to 'na piechotę' - w pliku funkcje.c 'wykomentowuje' wszystkie nieużywane. Próbowałem dołączać pliki dodatkowe .c w tym generatorze Mfile w opcji - Makefile c/c++ source files - ale po zapisaniu takiego pliku makefile kompilator zgłasza błąd.
  • #24 8162430
    acid12
    Poziom 21  
    tworzysz plik nagłówkowy z deklaracjami funkcji "funkcje.h" oraz plik z definicjami funkcji "funkcje.c".

    w 'funkcje.c' oraz pliku głównym robisz '#include "funkcje.h" '

    ---
    do projektu avr-studio dołączasz oba pliki (.h oraz .c)

    w makefilu dołączasz plik .c (jezeli robisz makefile'a recznie)

    ---

    serio zabrałeś się za nauke C od drugiej strony :|
  • #26 8162570
    gaskoin
    Poziom 38  
    tak, zauwaz, że do pliku main nie dodajesz #include "plik.c", dodajesz tylko nagłówek *.h
  • #27 8162640
    dziechu
    Poziom 27  
    Ok, wielkie dzięki. Jutro będę walczył z C dalej. Mam już zrobioną obsługę wyświetlacza graficznego, przetworników ADC, obsługę eepromu, klawiatury... zaczynam to wszystko układać w końcowy program - do tej pory testowałem działanie tych komponentów. Do bibliotek obsługi wyświetlacza dopisałem własne procedury wyświetlania dużych czcionek 24x36, utworzyłem plik czcionek, wszystko na razie działa bez problemu. Wielkie dzięki za pomoc. W książkach szukałbym tego z tydzień:)
  • #28 8162797
    acid12
    Poziom 21  
    dziechu napisał:
    To znaczy - wtedy kompilator dołączy tylko te funkcje z pliku .c które są zadeklarowane w pliku .h?


    w .h deklarujesz wszystkie funkcje jakie masz w .c
    to od ustawien kompilatora zalezy czy dolaczy wszystkie czy tez nie.

    wydaje mi sie ze gcc sam z siebie wie, ze ma nie dołączać kodu funkcji ktore nie sa wywoływane. Na kompilatorach sie nie znam, a na uC nigdy nie pisalem zbednych funkcji, zawsze wszystkie potrzebowałem :)
  • #29 8162849
    gaskoin
    Poziom 38  
    acid12 napisał:
    dziechu napisał:
    To znaczy - wtedy kompilator dołączy tylko te funkcje z pliku .c które są zadeklarowane w pliku .h?


    w .h deklarujesz wszystkie funkcje jakie masz w .c
    to od ustawien kompilatora zalezy czy dolaczy wszystkie czy tez nie.

    wydaje mi sie ze gcc sam z siebie wie, ze ma nie


    jezeli chodzi o AVR Studio to jak się dołączy plik *.h a nie użyje się jakiejś funkcji to on i tak ją dołącza do kompilacji. Także lepiej zakomentować te których się nie używa.

    GCC sam w sobie jest tylko głupim kompilatorem, i nie wydaje mi się żeby sprawdzał czy coś użyłeś czy nie tylko bierze jak leci
  • #30 8162863
    dziechu
    Poziom 27  
    Mam biblioteki na np. wyświetlacze graficzne, bardzo bogate, mają funkcje czcionek różnej wielkości, rysowania linii, okręgów, prostokątów, wrzucania bitmap... Dołączam taką bibliotekę, a jeżeli nie wszystkie funkcje wykorzystuję, to albo muszę je w danym projekcie wyciąć, albo zastosować sposoby jak wyżej. W asmblerze też zawsze pisałem sam procedury, mam wszystkie własne, obsługi różnych wyswietlaczy graficznych, alfanumerycznych, eepromow zewnetrznych itd.. Ale już mi się nie chce. Jak widzę opis obsługi wyświtlaczy kolorowych TFT z 1000 różnych rozkazów, to wolę gotowe biblioteki niż siedzieć całymi dniami i je tworzyć.
REKLAMA