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

[c][AVR studio 4] Problem z includowaniem.

pawelvod 27 Lut 2011 14:36 3816 30
  • #1 9211364
    pawelvod
    Poziom 18  
    Szukam i nie mogę znaleźć jak powinno wyglądać includowanie w przypadku AVR studio. Bez przerwy wywala mi błędy, że coś jest nie dołączone, albo że jest podwójna deklaracja jakiejś funkcji. Wg mojego zwyczaju gdy używałem winAVR w pliku main.c includowałem wszystkie definicje procesora, przerwania itd. Includowałem też własne biblioteki.c w których to były includowanie nagłówki .h
    Tutaj nie mogę zrobić tak, żeby program się odpalił. Jedyną opcją jaką udało mi się zmusić program złożony z kilku plików do działania było includowanie w zasadzie w każdym pliku wszystkiego.
  • #2 9211513
    tmf
    VIP Zasłużony dla elektroda
    A co do tego ma AVR Studio? Powinieneś poczytać raczej o podstawach C. Plików c się nie inkluduje, tylko dołącza do projektu, tak aby były oddzielnie kompilowane, a następnie linkowane. Inkluduje się wyłącznie pliki nagłówkowe (h). W wielu przypadkach prowadzi to do sytuacji takiej jaką masz - w wielu miejscach trzeba dołączać te same pliki.
  • #3 9211625
    pawelvod
    Poziom 18  
    No z AVR studio ma tyle wspólnego że pod winavr wszystko działą, a w avr studio nie chce. Co do includowania plików .c to uważąm, że jeśli coś jest jakąś biblioteką to robię tak jak piszesz, natomiast jeśli plik obsługi jakiegoś urządzenia ma 3000 linii to uciążliwe staje się poruszanie po nim. Wtedy dobrą opcją jest podzielenie go na 2 mniejsze. I na końcu jednego dorzucenie drugiej części. Tak żeby nie przewijać ekranu długi czas. Czy powiedzmy jakaś tablica w pamięci ram ma być zapisana (wewnątrz funkcji do lokalnego użytku) i niepotrzebnie wala się w kodzie. Jak dodam ją w nagłówku to będzie wkomponowywać się zawsze. Jeśli jest wewnątrz funkcji wg mnie skompiluje się tylko wtedy gdy ta funkcja będzie choć raz wywołana. W winavr wszystko działało jak potrzeba. Pomijając poprawność formalną takiego konstruowania kodu jak dam include <coś> to kompilator w pierwszym przejściu powinien skopiować plik "coś" i wkleić go dokładnie w miejsce include "coś".AVR studio nie robi tego chyba...?
  • #4 9211662
    Mad Bekon
    Poziom 23  
    Kolego pawelvod, masz mylne pojęcie.
    tmf dobrze Ci mówi. Właściwa droga to tworzenie par plik .h, plik.c.
    Do maina includujesz pliki .h które zawierają tylko deklaracje procedur. Definicje znajdują się w plikach .c. Pliki .c są kompilowane oddzielnie i dlatego nie dołącza się ich do pliku main, tylko do projektu. Działa to tak zarówno w AVR Studio jak i w WinAVR. A tak na prawdę z tego co wiem to oba i tak korzystają z GCC więc musi to działać w ten sam sposób.

    Może w WinAVR, a w zasadzie pewnie Programmers Notepad II, działa to dlatego, że twój plik Makefile sam przegląda pliki .c i je kompiluje.
    Mam nadzieje, że nie wpadłeś na pomysł w styly
    #include<plik.c>


    Tworzenie projektu i dołączenie do niego wszystkich plików czyli .c i .h to jedyne słuszne podejście.
  • #5 9211733
    pawelvod
    Poziom 18  
    No wiem, że mam mylne pojęcie bo kod który skleciłem nie chodzi:).
    Czyli podsumowując:
    - Tworzę pliki .c i we wszystkich nich includuję nagłówki .h wszystkich plików które będe w nich używał (nawet po kilka razy...)
    ... co z kodem static uint8_t bmp[64x64] PROGMEM = ... tutaj 64x64 bajtów.
    Jeśli includuję go w każdym pliku nie będzie on umieszczony w końcowym kodzie kilka razy?
    - #define PINUZYWANYWSZEDZIE PB0 umieszczam w uniwersalny_naglowek.h i includuję go w każdym pliku .c/ .h ???
    Zrobiłem tak jak mówicie i kod który zajmował 2424 bajtów po przeróbkach żeby chodziło pod AVR studio zajmuje
    Program: 10784 bytes (65.8% Full)
    optymalizacja -0s w obu przypadkach.
    Po prostu wszystkie tablice są umieszczone w kodzie maszynowym po kilka razy...
  • #7 9211802
    pawelvod
    Poziom 18  
    #include 	<avr/io.h>
    #include 	<avr/interrupt.h>
    #include 	<inttypes.h>
    //#include 	<avr/eeprom.h>
    #include	<avr/sleep.h>
    #include	<stdlib.h>
    #include 	<math.h>
    #include 	<avr/pgmspace.h> 
    #include 	<util/delay.h>
    #include 	"3510i.h"
    #include 	"font.h"

    to mój nagłówek każdego pliku .c na tą chwilę na początku kodu. To co proponujesz to x3 cała ta litania. głupie wyrzucenie czy dodanie czegoś to 2 minuty klepania w klawiaturę. Z resztą rzeczy (tablice) includowanie w jednym pliku muszą być includowane ponownie w drugim bo wywala błąd, że są nie zadeklarowane inaczej...
    Może jakieś GLOBAL?
    Nie wiem ponadto gdzie zdefiniować liczniki itd które muszą być widoczne we wszystkich bibliotekach. Teraz są to różne liczniki mimo tej samej nazwy...

    Proszę o umieszczenie kodu w znacznikach code.
    Robak
  • #8 9211920
    janbernat
    Poziom 38  
    Nie- w każdym z tych plików ***.h należy to umieścić- a nie w tej "litanii"
    Zobacz jak są zrobione pliki <***>.h wziete z biblioteki avrgcc.
    Swoje pliki "***".h należy zrobić tak samo.
  • #9 9212374
    pawelvod
    Poziom 18  
    Kurcze chyba po raz kolejny wrócę do notepada. Po umieszczeniu includów w plikach .h nie działą nic. Te if nic nie zmieniają. Tablice ładowane są wielokrotnie. W sumie przejście na AVR studio potrzebne jest mi do emulatora, bo upierdliwe jest skakanie między programami. Jedyną opcją jaka teraz daje rozsądną wielkość kodu i dostępność wszystkich zmiennych jest wwalenie całego kodu w jeden plik. Znacie może jakieś miejsce gdzie jest jasno opisane jak formalnie includować pliki żeby było ok. Chodzi mi o AVR C bo w C na PC nie mam problemu. Wszystko działa i robię tak jak piszecie. Tyle że w AVR dochodzi EEPROM, RAM ROM itd. Nie piszę wielkich kodów (w końcu to tylko 8kb). Chodzi jedynie o posiadanie obsługi przerwania zegarowego w osobnym pliku, a obsługi ADC w osobnym. Przy czym oba korzystają z tych samych tablic (tangensy, pierwiastki itd.). Może ktoś tak dla opornych;) potrafi mi powiedzieć jak to zrobić:

    plik main.c
    plik przerwanie.c
    plik adc.c

    zmienne które powinny być dostępne w każdym z plików:
    volatile 	uint32_t 	licznik;
    uint16_t 	temperatura			EEPROM = 270;
    static uint8_t font[8] PROGMEM = {21,12,12,34,34,34,34,32};
    

    Proszę o umieszczenie kodu w znacznikach code.
    Robak
  • #10 9213338
    janbernat
    Poziom 38  
    deklarujesz jako extern w jednym pliku a w pozostałych normalnie.
  • #11 9214847
    tmf
    VIP Zasłużony dla elektroda
    Kolego, C to C niezależnie, czy na mikrokontrolery, czy na PC. Więc ponowię radę - kup książkę do nauki C i ją przeczytaj, zanim zaczniesz coś pisać. Z twojego opisu wynika, że robisz babol na babolu, w dodatku bez zrozumienia co i po co się stosuje. Może to brutalne, ale prawdziwe. AVR Studio używa avr-gcc (czyli WinAVR) do kompilacji projektów w C, samo w sobie jest w tym przypadku wyłącznie edytorem. Jeśli są różnice, to dlatego, że w obu przypadkach różni się makefile. A różni się dlatego, że nieprawidłowo utworzyłeś projekt w AVR Studio, np. nie dodałeś wszystkich plików źródłowych. Plików źródłowych się nie inkluduje. Koniec, kropka. Tu nawet nie ma co dyskutować. Inkludujesz pliki nagłówkowe, które zawierają prototypy funkcji i deklaracje zmiennych. Tu mała podpowiedź - naucz się rozróżniać deklarację i definicję, to unikniesz problemów z wielokrotnym umieszczeniem tablic. W nagłówku ma być deklaracja, w niektórych przypadkach implikuje to użycia słowa kluczowego extern, zasadniczo wszystkie zmienne w nagłówkach mogą być zadeklarowane z extern. Kolejna rzecz - znowu podstawy c - jeśli deklarujesz i definiujesz jednocześnie zmienną ze słowem kluczowym static to ograniczasz jej zasięg, w efekcie kompilator musi tworzyć wielokrotne kopie zmiennej, bo przez ograniczony zasięg nie wie, że dana zmienna już została utworzona. Aby to ominąć należy używać zmiennych o zasięgu globalnym (kiepski pomysł) lub dodać słowo kluczowe extern - oczywiście w jakimś pliku musi być definicja zmiennej.
    Także podsumowując:
    1. Twój problem nie ma nic wspólnego z AVR Studio,
    2. Kup sobie książkę o C.
  • #12 9215515
    pawelvod
    Poziom 18  
    Z książkio C ktorą posiadam:
    Cytat:
    "include … - dyrektywa włączająca tekst innego pliku źródłowego w miejscu jej wystąpienia w pliku podlegającym aktualnie przetwarzaniu, przy czym możliwe jest zagłębione występowanie dyrektywy include

    Tylko to nie działa jak jest napisane że powinno...
  • #13 9215572
    tmf
    VIP Zasłużony dla elektroda
    Jasne, nie działa... bez jaj.
    Jak pisałem, przeczytaj co to jest definicja, a co to deklaracja, o prototypach funkcji i ogólnie o tym jak wygląda kompilacja i linkowanie w języku C. Dopiero jak to załapiesz, zacznij pisać program. Bez takich podstaw nic ci nie będzie działać.
  • #14 9215720
    pawelvod
    Poziom 18  
    No czytam już 3 dzień. Tylko że problem zaczyna się w przypadku PROGMEM i EEPROM. Nie ma tego opisanego w standardach C bo to rzecz swoista dla AVR. Tutaj zaczynają się problem z podwójnym dołączaniem. extern to informacja że zmienna będzie zadeklarowana potem, natomiast ja takiej informacji nie chcę przekazać kompilatorowi (może to i trick który działa ale formalnie extern nie do tego służy). Programuje już bodajże 30 lat z czego większość to assembler. Tam 64kb kodu tworzonej gry nie było dla mnie problemem. Niestety nawyki kontroli wszystkiego zostają i lubię wiedzieć dlaczego coś się dzieje. Co do formalnego zapisu kodu i odróżnieniu deklaracji od definicji nie miałem z tym nigdy problemu. Natomiast AVR i C to trochę naciąganie C do potrzeb mikrokontrolerów i proszac o pomoc nie liczyłem o wskazanie różnic. Co do podpowiedzi kup książkę to uważam, że w erze wikipedii i google to nietrafiony pomysł. Mam kilka książek o C i odpowiedzi tam nie znalazłem. Nie znalazłem ich także w google ani na tym forum. Stąd pytanie. Z resztą był ten temat kilkukrotnie podnoszony i zawsze kończył się stwierdzeniem kup książkę. Już zmieniłem makefile na mój stary plik i kompiluję tak jak kompilowałem przez lata wiedząc że jest to nie eleganckie aczkolwiek poprawne (jeden wielki plik). tmf powiem Ci jedno - na nauczyciela to ty się nie nadajesz;)
  • #15 9215855
    tmf
    VIP Zasłużony dla elektroda
    Trudno uczyć kogoś kto się uczyć nie chce i twierdzi, że on wszystko umie i robi jak robi, a kompilator jest zły, bo śmie mieć inne zdanie.
    C to C i na mikrokontrolerze jest dokładnie takie samo jak na PC. Skoro nie potrafisz rozwiązać problemu korzystając ze źródeł internetowych, to najwyraźniej jednak ma sens kupować książki, bo w każdej znanej mi książce poświęconej C jest dokładnie wytłumaczone to z czym masz problem. A twój problem niestety wynika z tego, że chcesz zmusić kompilator do zrobienia czegoś, czego się robić nie powinno (zainkludować plik zawierający źródła).
    Najwyraźniej też nie odróżniasz definicji od deklaracji - extern właśnie służy dokładnie do tego o czym tu piszemy - do poinformowania kompilatora jak wygląda deklaracja zmiennej, bez jej definiowania, w efekcie wielokrotnego włączania i rezerwowania dla niej miejsca. Atrybuty PROGMEM i EEPROM nie mają tu nic do rzeczy, bo są to tylko atrybuty. Wpływają one na umieszczenie zmiennej w pamięci, ale nie mają żadnego wpływu na wielokrotnej jej tworzenie i inne tego typu mecyje - bo to wynika wprost ze standardu języka C. No ale ty przecież nie chcesz się tego uczyć, bo wiesz swoje...
  • #16 9215918
    szelus
    Poziom 34  
    1. Kontrola nad kodem w przypadku C jest niemal taka sama jak w asm.
    2. C to jest w zasadzie "strukturalny asembler" :wink: i do mikrokontrolerów wcale nie trzeba go naciągać. Różne rodzaje pamięci w AVR narzucają konieczność kontroli - w asm także. I to jest poza standardowym C.
    3. Dyrektywa "include" w C działa tak samo, jak w asemblerze, jeżeli ten ostatni coś takiego wspiera - tworzy jeden wielki plik źródłowy zawierający w miejscach jest wystąpienia "wklejoną" zawartość odpowiednich plików. Wielokrotnie i/lub w sposób zagłębiony, jeżeli tak zażądał programista.
    4. Aby uniknąć wielokrotnych definicji przy wielokrotnym inkludowaniu tego samego pliku (problem pojawia się przy wielopoziomowym stosowaniu include) stosuje się technikę, o której wspomniał janbernat.
    5. Czy korzystałeś przy programowaniu w asemblerze z linkera i możliwości kompilowania programu z oddzielnych modułów? Prawdopodobnie nie, to by wyjaśniało niektóre Twoje problemy.
    6. Jeżeli program składa się z kilku niezależnie kompilowanych modułów i odwołują się one wzajemnie do siebie, to trzeba poinformować kompilator o symbolach w innych modułach. Do tego właśnie służą deklaracje - deklaracje zmiennych "extern" i prototypy funkcji.
    7. Aby umożliwić efektywne korzystanie z techniki opisanej w punkcie powyżej, przyjęło się umieszczać w plikach nagłówkowych tylko definicje typów i deklaracje, w dodatku obejmując cały plik przez #ifdef, jak opisał janbernat i nie inkludować plików ".c". Nie jest to wymaganie kompilatora, ale narzędzia programistyczne (IDE) są do takiego postępowania przystosowane, więc nie należy się dziwić, jak nie działają prawidłowo przy nietypowym podejściu.
    8. Definicji (tak zmiennych jak i funkcji) nie należy umieszczać w plikach nagłówkowych aby nie powodować wielokrotnego ich umieszczania w kodzie, co powinno być oczywiste, jeżeli uwzględnić to, co napisałem w punkcie 3 powyżej. Nie dotyczy to tylko funkcji inline.
    --edit--
    Moja odpowiedź to oczywiście do autora, posta kolegi tmf jeszcze nie było, jak pisałem.
  • #17 9216223
    pawelvod
    Poziom 18  
    Dzięki. Nareszcie coś do przodu. Linkera rzeczywioście używałem dawno temu, ale to ze względu na długi czas kompilacji całego kodu. W mikrokontrolerze i tak za każdym trzeba wrzucić całość do mikrokontrolera i na to głównie schodzi czas więc używanie skompilowanych bibliotek nie ma tu dla mnie jakiegoś wielkiego znaczenia. Jakbym mógł prosić jeszcze jedną rzecz tak łopatologicznie.
    To jest definicja którą powinienem umieścić w pliku .c .h?
    
    uint8_t font[8] PROGMEM = {21,12,12,34,34,34,34,32}; 
    

    Jak ją zadeklarować w innych bibliotekach, żeby kompilator czy linker nie wywalał jej braku i nie wsadził jej kodu podwójnie?
    extern uint8_t font[8] PROGMEM = {21,12,12,34,34,34,34,32};

    Czyli w wileu miejscach używam extern a tylko w jednym definiuję?
    Czy można jakoś nie wpisywać tych wartości {21,12,12,34,34,34,34,32} we wszystich miejscach, a tylko tam gdzie definiujemy?
    Czy jak taką definicję umieszczę w funkcji której ani razu nie użyję to nie zajmie ona tych 8 bajtów pamięci (nie będzie skompilowana)?
  • #18 9216297
    szelus
    Poziom 34  
    pawelvod napisał:

    To jest definicja którą powinienem umieścić w pliku .c .h?
    
    uint8_t font[8] PROGMEM = {21,12,12,34,34,34,34,32}; 
    


    To jest definicja; zdecydowanie w pliku C i tylko jednym.
    Cytat:

    Jak ją zadeklarować w innych bibliotekach, żeby kompilator czy linker nie wywalał jej braku i nie wsadził jej kodu podwójnie?
    extern uint8_t font[8] PROGMEM = {21,12,12,34,34,34,34,32};


    To w dalszym ciągu jest definicja. Deklaracja:
    extern uint8_t font[8] PROGMEM;

    Taką deklarację możesz umieścić wielokrotnie - jeżeli musisz.
    Cytat:

    Czy jak taką definicję umieszczę w funkcji której ani razu nie użyję to nie zajmie ona tych 8 bajtów pamięci (nie będzie skompilowana)?

    To czy użyjesz funkcji, czy nie, to nie ma znaczenia. Kompilator i tak ją skompiluje i doda do kodu. Chyba, że jest to funkcja klasy static, tzn. jawnie poinformujesz kompilator, że nie jest ona używana(nie jest wołana) w innym pliku(module).
    Inna sprawa to biblioteki.
    Nie do końca chyba rozumiem, co masz na myśli, że zdefiniujesz tą tablicę w funkcji? Jako static?
    No i na koniec - dzielenie kodu na moduły nie służy przyspieszaniu kompilacji a zwiększaniu jego przejrzystości i ułatwieniu ew. późniejszego, powtórnego wykorzystania.
  • #19 9216337
    pawelvod
    Poziom 18  
    Z tą funkcją to tak jak piszesz czyli:
    maluj_obrazek(){
    static uint8_t obrazek[64*64] PROGMEM = {.......};
    ...
    }

    Czy da się tak zrobić żeby ta funkcja była wkompilowana tylko wtedy kiedy choć raz zostanie użyta. Oczywiście z tego co wcześniej zrozumiałem obrazek tak czy siak fizycznie w kodzie maszynowym pojawi się tylko raz niezależnie ile razy wywołam funkcję?
  • #20 9216383
    szelus
    Poziom 34  
    A jak to rozwiązujesz w asemblerze?
    Rozwiązanie zależy od zapotrzebowania. O czego u Ciebie zależy, czy bedą odwołania? Rozumiem, że static nie załatwia sprawy, bo odwołania są z innych plików?
    Jeżeli chcesz stworzyć coś w rodzaju biblioteki, to nie ma lepszego rozwiązania niż stworzenie biblioteki - wóczas linker zadba o dołącznie tylko potrzebnych modułów bibliotecznych.
    Ewentualnie kompilacja warunkowa (ifdef).
  • #21 9216409
    tmf
    VIP Zasłużony dla elektroda
    Nie ma jednoznacznej odpowiedzi na to pytanie. Wszystko zależy gdzie ta funkcja zostanie umieszczona - w pliku nagłówkowym, czy źródłowym i od jej prototypu. O ile będzie w pliku źródłowym, a prototyp nie będzie zawierał static lub inline to funkcja zostanie stworzona tylko raz, niezależnie od ilości jej wywołań. Przy czym to też nie jest tak pewne - wszystko zależy od opcji kompilacji, w tym określonych kosztów inlinowania funkcji oraz możliwości utworzenia specjalizowanych wersji funkcji (począwszy od avr-gcc 4.4). Jedyne czego można być pewnym, to, że zmienna obrazek zostanie utworzona tylko jeden raz.
  • Pomocny post
    #22 9217213
    janbernat
    Poziom 38  
    Chyba jednak książki:
    http://atnel.pl/wydawnictwo
    To już jest- na przykładach można nauczyć się pisać porządnie.
    To będzie dopiero w maju:
    http://helion.pl/ksiazki/jezyk-c-dla-mikrokon...aplikacji-tomasz-francuz,jcmikr.htm?r_from=ls
    Zobaczymy co to będzie- ale i na pewno kupię.
    Ta strona- właśnie było włamanie ale chyba odblokują:
    http://4programmers.net/C/Extern
    No i chyba nie można deklarować zmiennej jako extern a potem definiować jako static.
    P.S.
    Pokaż drzewo - to z lewej strony- jakie masz pliki w AVRStudio.
  • Pomocny post
    #23 9218350
    szelus
    Poziom 34  
    janbernat napisał:

    No i chyba nie można deklarować zmiennej jako extern a potem definiować jako static.

    To może niuans, ale taka interpretacja nawet mi nie przyszła do głowy, jak czytałem pytania. :)
    W każdym razie - w tym samym kontekście, oczywiście, nie można. Ale jeżeli w innym (wewnątrz funkcji czy bloku), to można - będzie to inna zmienna, przesłaniająca definicję/deklarację tamtej.
  • #24 9218508
    pawelvod
    Poziom 18  
    Ok. Ogarnąłem, zastosowałem i wszystko działa ok. Natomiast mam jedną wątpliwość.
    Powiedzmy że mam:
    1. obsługę wyświetlacza plik wyswietlacz.c i wyswietlacz.h
    2. w pliku main.c includuję wyswietlacz.h
    3. ten sam wyswietlacz.h includuję w pliku wyswietlacz.c
    4. w pliku wyswietlacz.h mam deklarację zmiennej (uint8_t kolor_znaku;)
    Jako że 2 razy includowana jest deklaracja (raz w main.c raz w wyswietlacz.c) czy powinienem w pliku nagłówkowym zdefiniować ją jako extern? Co do książek to dzięki. Pewnie którąś rzeczywiście zamówię.
  • #25 9219449
    szelus
    Poziom 34  
    W tym przypadku kompilator sobie poradzi.
    Zmienne globalne, które nie są zadeklarowane jako static, są z definicji klasy extern. Jeżeli programista nie nadaje im początkowej wartości, to kompilatory przeważnie nadają im status symbolu wspólnego (common) dla linkera i umieszczają w sekcji bss (dane niezainicjowane), czyli będą współdzielone przez wszystkie pliki/moduły, które się do nich odwołują.
    Natomiast, gdy mają nadaną wartość początkową, kompilator umieści taką zmienną jako zwykły symbol w sekcji data. Z tego powodu nie można nadawać wartości początkowej zmiennym w plikach nagłówkowych - liker będzie miał problem z wielokrotnie zdefiniowanym symbolem. Zmienne globalne, współdzielone przez moduły, które mają nadaną gdzieś jawnie wartość początkową, powinny być w plikach nagłówkowych jawnie oznaczane przez extern.
  • #26 9219865
    pawelvod
    Poziom 18  
    To jeszcze jedno. Czy można w jakiś sposób zmusić kompilator żeby kompilował tylko te funkcje które są użyte chociaż raz?
  • #27 9220071
    tmf
    VIP Zasłużony dla elektroda
    Wracając do poprzedniego pytania to jest tak jak pisze szeluś, przy czym ponieważ to nic nie kosztuje, a pozwala unikać błędów (np. wielokrotnie inicjalizowane zmienne w różnych modułach) dodanie extern nie zawadzi.
    Co do kompilacji - chodzi ci o to, żeby funkcja zawsze istniała? Tego bezpośrednio nie da się zrobić w C, ale można korzystając z jego rozszerzeń, np. w gcc będzie to atrybut used dodany do funkcji. Natomiast jeśli chodzi ci o coś odwrotnego, czyli, żeby kod funkcji był generowany tylko dla funkcji użytych to sprawa nie jest prosta. Tu kompilator ma pole do popisu i może generować różne wersje funkcji dla różnych argumentów, może inlinować funkcję itd. Potencjalnie należałoby tak pisać kod aby wszystko było w jednym module, albo wręcz odwrotnie - jedna funkcja jeden moduł. Odpowiednio używać także static, w celu ograniczenia zasięgu symbolu, co też polepsza możliwości optymalizacji. Generalnie rozwiązanie nie jest takie proste i zahacza o optymalizację kodu, czyli mniej więcej dwa stopnie wyżej. Można to też osiągnąć odpowiednimi parametrami linkera.
  • #28 9220246
    szelus
    Poziom 34  
    pawelvod napisał:
    Czy można w jakiś sposób zmusić kompilator żeby kompilował tylko te funkcje które są użyte chociaż raz?

    Zasadniczo, nie odpowiedziałeś na zadane powyżej przeze mnie pytanie o funkcję celu.
    Jeżeli chodzi o to, że masz w kodzie bajzel i oczekujesz, że kompilator Cię wyręczy w zrobieniu porządku, to tak sie nie da.
    Jeżeli chodzi chodzi o to, żeby wygenerowac mały kod, to opcja -Os powinna zasadniczo sprawę załatwić. Chyba, że musisz wycisnąć wszystko z flash-a, do ostatniego bajtu, to wtedy mogą być potrzebne specjalnie techniki, ale to już będą sztuczki bardzo zależne od konkretnego kodu i (wersji) kompilatora.
    Jeżeli chcesz stworzyć bibliotekę, to tak jak pisałem ja, czy tmf , wskazane jest podzielić kod na niezależne kawałki zroganizowane w bibliotekę i zostawić linkerowi martwienie się o dołączanie tylko potrzebnych plików (półskompilowanych).
    Jest jeszcze sztuczka z -ffunction-sections, ale osobiście nigdy tego nie próbowałem.
  • #29 9220799
    pawelvod
    Poziom 18  
    Chodzi mi o sytuację gdzie piszę powiedzmy obsługę wyświetlacza i mam funkcje do malowania kółek, wypełniania pól, obracania trójwymiarowych siatek, czcionek różnych rozmiarów wraz z definicjami znaków itd. Includuję to tak jak mnie nauczyliście czyli tylko plik wyswietlacz.h z samymi deklaracjami (już nawet wszystko poprostowałem:)). Puki co używałem techniki zakomentowywania tych funkcji których nie użyję. Natomiast wygodne byłoby żeby kompilator sam wkompilował tylko te które choć raz gdziekolwiek kodzie użyłem.
  • Pomocny post
    #30 9220908
    tmf
    VIP Zasłużony dla elektroda
    Musisz umieścić jedną funkcję biblioteki w jednym pliku - efekt - masz tyle plików ile funkcji :) Linker wybierze potrzebne. Kompilator nie ma takiej możliwości. Są inne rozwiązania, ale to pod wieloma względami jest najlepsze. Takie pliki możesz prekompilować i utworzyć z nich prawdziwą bibliotekę dodawaną na etapie linkowania.
REKLAMA