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

WinAVR, pliki źródłowe c oraz nagłówkowe h i własn bibloteka

slawek55 03 Lip 2010 16:06 3323 26
  • #1 8257324
    slawek55
    Poziom 23  
    Cześć.
    Szukam odpowiedzi na może dość banalne pytanie, ale nie spotkałem odpowiedzi na to mimo że jest to dość oczywiste, tylko dlaczego.
    Otóż, piszę sobie program na jakiegoś AVR w WinAVR.
    Powiedzmy że program używa jakiś funkcji obsługujących np szynę 1-Wire.
    Więc zgodnie z dobrymi zasadami wszystkie funkcje związane z obsługą szyny 1-Wire oddzielamy od głównego programu do osobnego pliku.
    Zwykle mamy wtedy pliki main.c oraz 1wire.c i 1wire.h
    Ale moje pytanie brzmi tak. Dlaczego te funkcje znajdują się w pliku 1wire.c?
    Czy nie możemy po prostu skopiować wszystkich funkcji do pliku 1wire.h i dodać do programu głównego poprzez #include?
    Przecież jak mamy dwa osobne pliki źródłowe z końcówką c to w pliku Makefile musimy dodać do kompilacji te pliki źródłowe. A jak korzystamy z bibliotek z pakietu WinAVR np do obsługi Watchdoga to nie dodajemy tego do makefile tylko poprzez #include?

    Gdzie tu jest haczyk?
  • #2 8257414
    livex21
    Poziom 22  
    Przez include dodajemy tylko pliki *.h, które zawierają nagłówki funkcji zamieszczonych w pliku *.c.

    Nie rozumie kolegi pytania?
  • #3 8257433
    krdln
    Poziom 13  
    Funkcje są w pliku .c, żeby za każdym razem ich nie kompilować. W .h wrzuca się tylko nagłówki. Jak się dobrego makefile'a będzie miało to 1wire.c skompiluje się tylko raz i potem będzie tylko łączony z mainem. Ale oczywiście nic nie szkodzi wrzucić całe funkcje do pliku .h, nie jest to, co prawda, „piękne” rozwiązanie – plik ten w trakcje kompilacji jest jakby wklejany do maina i i tak się kompiluje wszystko, jedyna korzyść to większy porządek. Ale ja tak np. robię i jest fajnie :)
  • #4 8257563
    slawek55
    Poziom 23  
    Ja rozumiem różnice pomiędzy plikami .c oraz .h, tzn do czego one służą itd.
    Nie rozmiem tylko dlaczego jak wydzielimy z programu głównego pliki biblioteki np wspomnianą obsługę 1-Wire to musimy to dodać do Make file, przecież wtedy piszemy np SRC= main.c LCD_44780.c
    Jakby wszystko było w pliku hto pozostałoby tylko SRC=main.c
    A dlaczego w takim razie jak korzystamy z bibliotek WinAVR np wdt.h to tylko załączamy ten plik poprzez #include i w Makefile nie ma wdt.c?
  • #5 8257582
    romario4
    Poziom 16  
    Może jest to nie eleganckie, ale mniej mam później roboty, więc deklaracje i definicje funkcji umieszczam w pliku.h. Dodatkowo każdą funkcję deklaruję jako 'static', dzięki temu linkowane są tylko używane funkcje.
    Pozdrawiam.
  • #6 8257588
    mirekk36
    Poziom 42  
    slawek55 --> nie ma wdt.c bo to jest w bibliotekach właśnie. A ty robisz błędne założenia, że twoje pliki *.c oraz *.h to jakieś biblioteki. Tak mówi się na nie potocznie ale nie ma to nic wspólnego z bibliotekami czyli plikami *.o

    Poza tym skorzystaj z jakiegoś środowiska jak np Avr Studio albo Eclipse albo jeszcze coś innego - które to same za ciebie tworzą "w locie" plik makefile i nie trzeba się z nim w ogóle bawić. A za to będziesz mógł podglądać jak on jest tworzony jeśli już będziesz miał wielką potrzebę, żeby samemu w nim grzebać.

    Dodano po 3 [minuty]:

    romario4 napisał:
    Może jest to nie eleganckie, ale mniej mam później roboty, więc deklaracje i definicje funkcji umieszczam w pliku.h. Dodatkowo każdą funkcję deklaruję jako 'static', dzięki temu linkowane są tylko używane funkcje.
    Pozdrawiam.


    Co to za robota? ;) ktoś kto wymyślił standard C , podział na pliki *.c i *.h miał głowę na karku. Zatem można robić tak jak ty, można nawet robić jeszcze większe dziwne rzeczy jak niektórzy np includują pliki *.c ...... ale warto od początku przyzwyczaić się i pisać tak jak się należy, bo kiedyś zwykle i tak przyjdzie olśnienie i opamiętanie ... a wtedy nie będzie męczarni z zaglądaniem do ... czy przerabianiem starych projektów.
  • #7 8257645
    slawek55
    Poziom 23  
    Tak masz rację. Popatrzyłem właśnie do plików .h z WinAVR i np w pliku wdt.h są całe funkcje i pewnie dlatego wystarczy dodać poprzez #include <wdt.h> i nie trzeba dodawać do makefile i dlatego pewnie nie ma plików wdt.c
    Zastanawiam się teraz skoro całe funkcje można przenieść do plików h to po co robi się podział na pliki .c i .h? To w penym sensie jakaś komplikacja całości. Choc pewnie sa wieksze zalety?
  • #8 8257663
    tmf
    VIP Zasłużony dla elektroda
    mirekk36 - tak pro forma to pliki z rozszerzeniem o to nie biblioteki, biblioteki mają rozszerzenie a i składają się z archiwum plików obiektowych o. Oczywiście jak zwykle się czepiam szczegółów :)
    Co do podstawowego pytania. Oczywiście możesz deklaracje i definicje funkcji umieszczać w plikach nagłówkowych, nikt ci tego nie zabroni, ba, jest to nawet zgodne ze standardem. Tylko teraz pomyśl co się stanie jeśli taki nagłówek zainkludujesz kilka razy w różnych plikach źródłowych i innych nagłówkach. To co wymyślisz będzie odpowiedzią na pytanie dlaczego tak nie należy robić.
  • #9 8257732
    slawek55
    Poziom 23  
    No właśnie, pewnie o to chodzi, nie można utworzyć funkcji delay w kilku miejscach a tak by się stało, czy dobrze rozumiem?
    A to co pisałeś ze to zgodne ze standardem, to masz moze pod ręką opis do tego, bo ja szukałem w książce o C i nie znalazłem?
    A przy okazji, czy jest mozliwość zrobienia własnych bibliotek w WinAVR?
  • #10 8257788
    tmf
    VIP Zasłużony dla elektroda
    Oczywiście, że jest - avr-ar. Standard c znajdziesz bez problemu w necie. Co do nagłówków to słusznie się domyślasz - w zależności od opcji z którymi kompilujesz albo miałbyś błąd, albo wielokrotne kopie tych samych funkcji. Stąd też ciała funkcji w plikach nagłówkowych występują właściwie wyłącznie w przypadku funkcji inline.
  • #11 8257914
    PO.
    Poziom 20  
    Przyłączę się do tematu i pytania - bo próbuję się przesiąść z avrstudio na eclipse i to co to pierwsze puszczało bez problemu, drugie odrzuca z głupimi błędami. Używam czegoś, czego nie nazwalibyście biblioteką :/ czyli gołych plików *.c, bez plików nagłówkowych, zazwyczaj nie prototypuję funcji bo nie mam takiej potrzeby, deklaracja jest od razu definicją, pliki includuję sobie w głównym pliku. No i eclipsowi nie podobają się funkcje więcej niż jednoargumentowe - to kwestia braku plików nagłówkowych, braku prototypów, czy jeszcze jakiś myk? Avrstudio kompiluje to samo bez błędów.
  • #12 8257949
    tmf
    VIP Zasłużony dla elektroda
    PO. nie obraź się ale robisz coś totalnie głupiego i jeszcze prosisz nas o pomoc jak kontynuować te dziwaczne praktyki? Zacznij pisać jak należy to nie będzie problemów - to jedyna sensowna możliwość.
  • #13 8257997
    PO.
    Poziom 20  
    Nie chcę się obrażać, szczególnie na Ciebie ;) ale to co robię jest zgodne ze standardem - na ile się zorientowałem. Czy nie jest?
    Widzę, że będzie ciążył na mnie teraz poprzedni wątek, prosiłem moderatora żeby go podzielił ale wolał zamknąć :( a wszyscy skupiali się nie na pytaniu tylko na bzdurach (żeby nie napisać ostrzej). Nasuwa mi się refleksja, że na elce można pytać o miganie ledkami tylko bo każda poważniejsza wiedza jest zbyt cenna...

    Ad rem: wiem, jest to mocno na skróty ale było wygodne i proste więc że działało zacząłem to robić. Pewnie będę docelowo zmieniał podejście ale nie dziś jeszcze - i nie wszystko co piszę będę zmieniał na to co proponujesz bo wygodniej mi jest w tej wprowadzać zmiany w tej nie_bibliotece na bieżąco i kompilować ją za każdym razem. No i na pewno nie dziś, muszę robić inne rzeczy na bieżąco i szybciej będzie wrócić do avrstudio niż eksperymentować z eclipsem nie wiedzac czy i kiedy zadziała.
    Poczytałem sobie tutoriale i chyba rozumiem założenia pisania bibliotek ;) ale też się chcę dowiedzieć jak najwięcej zanim zacznę "poprawiać".
  • #14 8258060
    mirekk36
    Poziom 42  
    tmf napisał:
    mirekk36 - tak pro forma to pliki z rozszerzeniem o to nie biblioteki, biblioteki mają rozszerzenie a i składają się z archiwum plików obiektowych o. Oczywiście jak zwykle się czepiam szczegółów :)
    .


    Nie, nie czepiasz się. Święta racja ... pomyliło mi się.

    Dodano po 10 [minuty]:

    PO. napisał:
    ale to co robię jest zgodne ze standardem - na ile się zorientowałem. Czy nie jest?


    No to jak to jest z tobą? Ty pytasz czy to co robisz jest zgodne ze standardem? czy stwierdzasz, że jest to zgodne ze standardem. Jak zwykle mieszasz na maxa. I nie ma to nic wspólnego z tym "innym bezsensownym wątkiem, gdzie wszyscy się rzekomo ciebie czepiali". A teraz wychodzi na to, że wyciągasz wnioski jakoby można się było tylko pytać na elektrodzie o miganie LEDem.

    Tak jak poprzednio tak i tutaj, można powiedzieć, że robisz pomieszanie z poplątaniem na maxa. Jak zwykle wszystko od tylca i nagle jesteś zdziwiony, że Eclipse czegoś nie kompiluje. Ja pracuję tylko w Eclipse jeśli chodzi o AVRki i zawsze działa świetnie. Na początku jak mi coś nie wychodziło to szukałem błedów w tym co robię czy myślę a nie dziury w całym.


    PO. napisał:
    Używam czegoś, czego nie nazwalibyście biblioteką :/ czyli gołych plików *.c, bez plików nagłówkowych, zazwyczaj nie prototypuję funcji bo nie mam takiej potrzeby, deklaracja jest od razu definicją, pliki includuję sobie w głównym pliku. No i eclipsowi nie podobają się funkcje więcej niż jednoargumentowe - to kwestia braku plików nagłówkowych, braku prototypów


    No to właśnie robisz bzdury nad bzdurami, popełniając kardynalne błędy i jak zwykle jak ktoś ci podpowiedział wyżej, że źle - to ty znowu obrażony na cały świat i elektrodę, że nikt nie poradzi ci jak ZMIENIĆ STANDARDY PISANIA W C.


    PO. napisał:
    Poczytałem sobie tutoriale i chyba rozumiem założenia pisania bibliotek ;) ale też się chcę dowiedzieć jak najwięcej zanim zacznę "poprawiać".


    Przeczysz sam sobie. Jakbyś poczytał to byś nie wypisywał takich bdur na maxa:

    PO. napisał:
    ... i nie wszystko co piszę będę zmieniał na to co proponujesz bo wygodniej mi jest w tej wprowadzać zmiany w tej nie_bibliotece na bieżąco i kompilować ją za każdym razem


    Kurczę, "w nie_bibliotece" , "mi jest wygodniej robić inaczej" .... to ty piszesz w C czy w jakimś własnym narzeczu. Popracuj może stworzysz jakiegoś nowego Pascala na tej swojej bazie.
  • #15 8258205
    PO.
    Poziom 20  
    mirekk36 napisał:

    No to jak to jest z tobą? Ty pytasz czy to co robisz jest zgodne ze standardem? czy stwierdzasz, że jest to zgodne ze standardem.


    Według tego co znalazłem jest ale nie czuję się nieomylnym absolutem jak co poniektórzy i dopuszczam możliwość popełnienia błędu - stąd, jeśli ktoś uważa że nie jest i może podać dobre źródło na potwierdzenie to poproszę; i tego dotyczy zapytanie.
  • #17 8258430
    Freddie Chopin
    Specjalista - Mikrokontrolery
    PO. napisał:
    zazwyczaj nie prototypuję funcji bo nie mam takiej potrzeby

    No to skoro nie masz takiej potrzeby, to niestety nie można Ci pomóc - to przypadek beznadziejny.

    Cytat:
    deklaracja jest od razu definicją

    "Jakby babcia miała wąsy to by była dziadkiem"

    Cytat:
    No i eclipsowi nie podobają się funkcje więcej niż jednoargumentowe

    Brzydki eklips! A fe!

    4\/3!!
  • #18 8261280
    romario4
    Poziom 16  
    mirekk36 napisał:
    Co to za robota? ktoś kto wymyślił standard C , podział na pliki *.c i *.h miał głowę na karku. Zatem można robić tak jak ty, można nawet robić jeszcze większe dziwne rzeczy jak niektórzy np includują pliki *.c ...... ale warto od początku przyzwyczaić się i pisać tak jak się należy, bo kiedyś zwykle i tak przyjdzie olśnienie i opamiętanie ... a wtedy nie będzie męczarni z zaglądaniem do ... czy przerabianiem starych projektów.

    Więc zapewne masz napisane tym sposobem bibliotekę do obsługi magistrali 1wire, którą chętnie się podzielisz, i wyjaśnisz mi jak mam to prosto zrobić żeby wykorzystując jedną lub kilka ( ale nie wszystkie ) funkcje z twojej biblioteki, w rezultacie nie otrzymał hex'a ze wszystkimi funkcjami z tej biblioteki nawet gdy nie użyję żadnej.
  • #19 8261355
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Sto tysięcy razy już było pisane o znaczeniu opcji kompilacji -ffunction-sections -fdata-sections i opcji linkowania --gc-sections. No ale komu by się chciało samemu pomyśleć, poczytać lub poszukać? Prościej założyć, że kompilator rozwijany od kilkunastu lat jest tak głupi, że jedynym wyjściem jest oszukiwać go inkludując wszystko do jednego pliku!

    4\/3!!
  • #20 8261458
    mirekk36
    Poziom 42  
    romario4 napisał:

    Więc zapewne masz napisane tym sposobem bibliotekę do obsługi magistrali 1wire, którą chętnie się podzielisz, i wyjaśnisz mi jak mam to prosto zrobić żeby wykorzystując jedną lub kilka ( ale nie wszystkie ) funkcje z twojej biblioteki, w rezultacie nie otrzymał hex'a ze wszystkimi funkcjami z tej biblioteki nawet gdy nie użyję żadnej.


    A co ma piernik do wiatraka??? (co ma icludowanie plików nagłówkowych *.h z definicjami funkcji w plikach *.c do bibliotek w plikach *.a ????)

    Poczytaj sobie to o czym pisał wyżej kolega to dowiesz się jak zrobić sobie biblioteki.

    A i bez bibliotek można sobie poradzić w pewnych sytuacjach. Wystarczy tylko pewne główne funkcje umieścić w oddzielnych plikach *.c i kompilator tylko je wykorzysta. Tyle, że trzeba dobrze zrozumieć jak to działa i troszkę w takim przypadku pożonglować plikami - ale da się zrobić. Szczególnie gdy piszesz coś na własny użytek.
  • #21 8261820
    tmf
    VIP Zasłużony dla elektroda
    Dzięki opcjom, które podał Freddie nie trzeba nawet żonglować. Każda funkcja znajdzie się wtedy w swojej sekcji i linker to potraktuje tak jakby każda była w swoim własnym pliku o. Do tego można dodać jeszcze optymalizację całości (wymagającą wywołania wszystkich jednostek kompilacji jednocześnie) i wszystko co nieużywane zostanie wyrzucone. No ale jak to zwykle bywa początkujący widzą głównie błędy w kompilatorze, a nie u siebie :)
  • #22 8263257
    romario4
    Poziom 16  
    Freddie Chopin napisał:
    Sto tysięcy razy już było pisane o znaczeniu opcji kompilacji -ffunction-sections -fdata-sections i opcji linkowania --gc-sections. No ale komu by się chciało samemu pomyśleć, poczytać lub poszukać? Prościej założyć, że kompilator rozwijany od kilkunastu lat jest tak głupi, że jedynym wyjściem jest oszukiwać go inkludując wszystko do jednego pliku!

    4\/3!!

    Ciekawe czemu twórcy pakietu WinAVR rozwijanego od kilkunastu lat nie pomyśleli i nie dołączyli wyżej wspominanych opcji do pliku Makefile (choćby w komentarzu) rozpowszechnianego razem z pakietem. Męczę się z tymi opcjami już drugi raz lecz bez powodzenia - linkują się wszystkie funkcje, nawet te nie używane.
  • #23 8263299
    Freddie Chopin
    Specjalista - Mikrokontrolery
    romario4 napisał:
    Ciekawe czemu twórcy pakietu WinAVR...

    WinAVR to zaledwie "paczka" ze skompilowanym toolchainem avr-gcc...

    Cytat:
    ... rozwijanego od kilkunastu lat...

    Pierwsze wydanie tej paczki - 2002-11-11, to raczej niezbyt kwalifikuje się na "kilkanaście".

    Cytat:
    nie pomyśleli i nie dołączyli wyżej wspominanych opcji do pliku Makefile (choćby w komentarzu) rozpowszechnianego razem z pakietem.

    Od myślenia jesteś ty, a nie ktośtam. Poza tym jeśli wolisz korzystać z gotowców, to Twój wybór i Twój problem.

    Cytat:
    Męczę się z tymi opcjami już drugi raz lecz bez powodzenia - linkują się wszystkie funkcje, nawet te nie używane.

    Bo coś źle robisz. Mamy sobie wywróżyć co dokładnie, skoro nie pokazałeś tego pliku makefile albo wywołań kompilatora _i_ linkera?

    4\/3!!
  • #24 8263519
    romario4
    Poziom 16  
    Proszę bardzo. Prosty przykład w załączniku. Plik 1wire.c z kilkoma funkcjami, plik 1wire.h z definicjami i plik main.c nie wykorzystujący żadnej z nich, oraz plik Makefile. W wyniku kompilacji otrzymuję plik dwa razy większy niż jakbym skompilował sam plik main.c
    A oto fragment przebiegu kompilacji:
    
    -------- begin --------
    avr-gcc (GCC) 4.3.4
    Copyright (C) 2008 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    
    Compiling C: main.c
    avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -fdata-sections -ffunction-sections -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./main.lst  -std=gnu99 -MMD -MP -MF .dep/main.o.d main.c -o main.o 
    
    Compiling C: 1wire.c
    avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -fdata-sections -ffunction-sections -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./1wire.lst  -std=gnu99 -MMD -MP -MF .dep/1wire.o.d 1wire.c -o 1wire.o 
    
    Linking: main.elf
    avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -fdata-sections -ffunction-sections -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o  -std=gnu99 -MMD -MP -MF .dep/main.elf.d main.o 1wire.o --output main.elf -Wl,-Map=main.map,--cref --gc-sections     -lm
    
  • #25 8263749
    Freddie Chopin
    Specjalista - Mikrokontrolery
    No i jest źle, bo:
    1. faza linkowania nie wymaga opcji -fdata-sections -ffunction-sections - są to tylko opcje kompilacji
    2. opcja --gc-sections wcale nie trafia do linkera. Do linkera trafiają za to (m.in.) opcje -Map=main.map oraz --cref. Teraz sam dojdź do tego co zmienić.

    4\/3!!
  • #26 8264170
    romario4
    Poziom 16  
    Freddie Chopin napisał:
    No i jest źle, bo:
    1. faza linkowania nie wymaga opcji -fdata-sections -ffunction-sections - są to tylko opcje kompilacji
    2. opcja --gc-sections wcale nie trafia do linkera. Do linkera trafiają za to (m.in.) opcje -Map=main.map oraz --cref. Teraz sam dojdź do tego co zmienić.

    4\/3!!

    No i faktycznie miałeś rację. Jeśli chodzi o pkt. 2 to w pliku makefile zmiłem lnijkę
    LDFLAGS += --gc-sections

    na
    LDFLAGS += -Wl,--gc-sections

    i radykalnie zmniejszył się rozmiar kodu.
    Jeśli chodzi o pkt. 1 to nie wiem czy mogę usunąć z fazy linkowania wszystkie opcje znajdujące się pod zmienną ALL_CFLAGS, czy tylko te dwie konkretne, a konkretnie w pliku Makefile jest:
    # Link: create ELF output file from object files.
    .SECONDARY : $(TARGET).elf
    .PRECIOUS : $(OBJ)
    %.elf: $(OBJ)
    	@echo
    	@echo $(MSG_LINKING) $@
    	$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
    

    czy może być:
    # Link: create ELF output file from object files.
    .SECONDARY : $(TARGET).elf
    .PRECIOUS : $(OBJ)
    %.elf: $(OBJ)
    	@echo
    	@echo $(MSG_LINKING) $@
    	$(CC) $^ --output $@ $(LDFLAGS)
    
    

    bo jak tak zrobię to rozmiar kodu zmalał do ok 50 bajtów, kiedy czysta funkcja main wcześniej zajmowało 114 bajtów.
  • #27 8264198
    Freddie Chopin
    Specjalista - Mikrokontrolery
    No to zignoruj tą kwestię - opcje nie są potrzebne, ale niczemu nie przeszkadzają. Musiałbyś zmienić Makefile tak aby do linkera nie były przekazywane wszystkie opcje kompilatora, ale chyba nie ma sensu.

    4\/3!!
REKLAMA