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

[Rozwiązano] [avr-gcc] Konflikt typów przy wywołaniu funkcji przerwaniowej INT0_vect na atmega8

trol.six 29 Kwi 2021 09:46 618 12
REKLAMA
  • #1 19407035
    trol.six
    Poziom 31  
    Posty: 1650
    Pomógł: 151
    Ocena: 381
    Mam taki kod przykładowy:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    kompilacja:
    Cytat:
    gcc -DF_CPU=11059200UL -Os -std=c89 -pedantic -Wall -Wextra -mmcu=atmega8 -c test.c -o test.o


    i kompilator rzuca:

    Cytat:

    avr-gcc -DF_CPU=11059200UL -Os -std=gnu99 -Wstrict-prototypes -pedantic -Wall -Wextra -mmcu=atmega8 -c test.c -o test.o
    In file included from test.c:8:
    test.c:24:5: warning: conflicting types for '__vector_1'
    24 | ISR(INT0_vect){
    | ^~~~~~~~~
    In file included from /usr/avr/include/avr/io.h:99,
    from test.c:5:
    test.c:21:2: note: previous implicit declaration of '__vector_1' was here
    21 | INT0_vect();


    Jak dam w odwrotnej kolejności, czyli

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    nie mam komunikatu. Ciekawe jest to że w jednym programie mam właśnie odwrotnie i dla atmegi8 komunikatu brak w obu przypadkach, natomiast dla atmegi328 jest.

    Zdawało mi się że wystarczy dodać pliki nagłówkowe od interrupt, aby funkcja była zadeklarowana. Skąd to zachowanie kompilatora? I czy w ogóle to jest dobrze? Albo co jest źle?
    .
  • REKLAMA
  • #2 19407090
    simw
    Poziom 27  
    Posty: 762
    Pomógł: 94
    Ocena: 288
    Zastanawia mnie dlaczego w ogóle wywołujesz tę funkcję przerwaniową. Przecież funkcja przerwaniowa "sama się wykona" jeśli nadejdzie przerwanie. Jeśli przerwania nie ma to po co wywoływać funkcję przerwaniową? Jak dla mnie to "dość dziwny" przykład, ale może czegoś tu nie rozumiem w Twoich zamiarach.
  • #3 19407099
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    makro, static inline itd itd, rozwiązań problemu jest wiele.
  • REKLAMA
  • #4 19407286
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Rozwiązań jest wiele, ale trzeba najpierw zrozumieć problem, a ten nie ma nic wspólnego z przerwaniami i wynika wyłącznie z definicji języka C.
    Wywołujesz funkcję przed zdefiniowaniem jej - i w tym momencie kompilator tworzy jej domyślny prototyp. Następnie definiujesz funkcję w sposób inny niż to, co sobie wymyślił kompilator - i masz informację o konflikcie. Zamień kolejność - procedurę, która woła funkcję, umieść po definicji funkcji - i kompilator przestanie marudzić.
  • REKLAMA
  • Pomocny post
    #5 19407309
    ex-or
    Poziom 28  
    Posty: 785
    Pomógł: 147
    Ocena: 151
    INT0_vect oraz ISR() to makra.Rozwija się to mniej więcej tak
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Przy wywołaniu w funkcji portchange() kompilator nie miał wcześniejszej deklaracji funkcji __vector_1 więc przyjął że funkcja zwraca wartośc o domyślnym typie a więc int. Ponieważ dalej funkcja zostaje zdefiniowana z typem void więc jest warning o sprzeczności typów. The end.
  • #6 19407711
    trol.six
    Poziom 31  
    Posty: 1650
    Pomógł: 151
    Ocena: 381
    Czyli wywoływanie takiej funkcji w innym pliku typowo "nie zadziała" w tym przypadku? Bo jeśli dobrze rozumiem, definiowanie samemu tych że funkcji, jest raczej pozbawione sensu w tym przypadku.

    simw napisał:
    Zastanawia mnie dlaczego w ogóle wywołujesz tę funkcję przerwaniową.

    Choćby do testu. :) Można to zrobić inaczej, ale interesuje mnie tutaj ten przypadek.
    .
  • #7 19407874
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Oczywiście, że by zadzaiało. Po prostu zrób z nią dokładnie to samo, co z każdą inną funkcją w C. Przed wywołaniem kompilator musi widzieć prototyp, inaczej masz ten efekt, jaki obserwujesz, i nie ma to nic wspólnego z przerwaniami.
    Patrz na ostrzeżenia - dobrze napisany program nie powinien generować żadnych.
  • #8 19408032
    ex-or
    Poziom 28  
    Posty: 785
    Pomógł: 147
    Ocena: 151
    Używając ISR jako zwykłą funkcję trzeba pamiętać, że wyjście z niej włącza przerwania.
    Prolog i epilog ISR jest dłuższy niż zwykłej funkcji gdyż zachowywane/odtwarzane są rejestry, ktrórymi zwykła funkcja się nie zajmuje (rejestr statusowy, r0, r1 oraz w razie użycia rejestry call-used).
  • #9 19408129
    trol.six
    Poziom 31  
    Posty: 1650
    Pomógł: 151
    Ocena: 381
    BlueDraco napisał:
    Oczywiście, że by zadzaiało. Po prostu zrób z nią dokładnie to samo, co z każdą inną funkcją w C.

    Nie moge z nią zrobić jak z inną funkcją bo funkcja przerwaniowa ma określony adres. A inna funkcja ląduje tam gdzie ląduje.

    BlueDraco napisał:
    Przed wywołaniem kompilator musi widzieć prototyp, inaczej masz ten efekt, jaki obserwujesz, i nie ma to nic wspólnego z przerwaniami.

    No to jak skonstruować taki kod dla avr-gcc? Aby jeszcze był przenośny pomiędzy atmegami?
    .
  • #10 19408347
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    trol.six napisał:
    Nie moge z nią zrobić jak z inną funkcją bo funkcja przerwaniowa ma określony adres. A inna funkcja ląduje tam gdzie ląduje.
    Nie, to adres tej funkcji umieszczany jest w odpowiednim miejscu.

    trol.six napisał:
    No to jak skonstruować taki kod dla avr-gcc? Aby jeszcze był przenośny pomiędzy atmegami?


    Najlepiej static inline i w obu miejscach wywołać taką funkcję,
  • #11 19409113
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Jak wyżej - to nie ma nic wspólnego z przerwaniami ani z AVR. Prototyp funkcji (a nie cała funkcja) musi być widoczny dla kompilatora przed wywołaniem funkcji - to wszystko.
  • REKLAMA
  • #12 19410831
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    BlueDraco napisał:
    Jak wyżej - to nie ma nic wspólnego z przerwaniami ani z AVR.


    Tym bardziej jest to rozwiązanie uniwersalne.

    BlueDraco napisał:
    Prototyp funkcji (a nie cała funkcja) musi być widoczny dla kompilatora przed wywołaniem funkcji - to wszystko.


    Przerwanie nie koniecznie musi być wywoływane jak standardowa funkcja.
  • #13 19411385
    trol.six
    Poziom 31  
    Posty: 1650
    Pomógł: 151
    Ocena: 381
    Post ex-or wraz kodem, wyjaśnia sytuacje:

    ex-or napisał:
    INT0_vect oraz ISR() to makra.Rozwija się to mniej więcej tak
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Przy wywołaniu w funkcji portchange() kompilator nie miał wcześniejszej deklaracji funkcji __vector_1 więc przyjął że funkcja zwraca wartośc o domyślnym typie a więc int. Ponieważ dalej funkcja zostaje zdefiniowana z typem void więc jest warning o sprzeczności typów. The end.


    .

Podsumowanie tematu

LABEL_AI_GENERATED
W dyskusji poruszono problem konfliktu typów przy wywołaniu funkcji przerwaniowej INT0_vect na mikrokontrolerze ATmega8. Użytkownik zauważył, że kompilator zgłasza błąd, gdy funkcja portchenge() wywołuje INT0_vect przed jej definicją. Odpowiedzi wskazują, że problem wynika z braku wcześniejszej deklaracji funkcji, co prowadzi do domyślnego przyjęcia typu zwracanego jako int, a nie void. Uczestnicy sugerują, aby zmienić kolejność definicji funkcji lub użyć makr, takich jak static inline, aby zapewnić przenośność kodu między różnymi modelami ATmega. Podkreślono również, że funkcje przerwaniowe mają określony adres, co różni je od standardowych funkcji w C.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA