Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[atmega...][c]Masakrowanie przerwań - luźne dywagacje...

PO. 02 Cze 2010 17:31 6534 91
  • #31 02 Cze 2010 17:31
    PO.
    Poziom 20  

    utak3r napisał:
    mirekk36 napisał:
    ...[ciach]... to mniej więcej to samo co pisanie całego programu w Basicu przy użyciu jedynie poleceń GOTO ...[ciach]...


    Gadasz... nie tak dawno na forum widziałem program napisany w C, którego pętla główna została zrealizowana przy pomocy... labelki i goto :D


    Bardzo fajna pętla :) . I zajmuje, zdaje się, mniej niż for(;;); albo while(); . Ale widać, niekoszerna jest...
    PS: wstawia w for buźkę, ma być:
    Code:
    for(;;);


    Dodano po 1 [minuty]:

    tmf napisał:
    Jeśli chcesz podmienić adres powrotu to praktycznie procedura musi być naked, bo musisz napisać swój epilog - adres powrotu jest najniżej, więc trzeba najpierw wszystko pozdejmować, ew. w prologu zapamiętać gdzie jest adres powrotu. Żeby móc całą procedurę ciągle napisać w C najłatwiej jest wtedy na stos odłożyć wszystkie rejestry mogące być zmodyfikowane przez procedurę... czyli robi się to trochę nieefektywne, chociaż strata kilku cykli przy procedurze trwającej kilkaset zapewne nie jest dotkliwa, szczególnie jeśli robisz task switching z koniecznym przełączeniem kontekstu procesora.
    Co do atomowości to zapewnić trzeba niestety nie tylko atomowość procedur arytmetycznych, ale także pewnych bloków programu, co już jest bolesne. Np. If(counter) counter--; musi być wykonane atomowo - nie wystarczy, że sama dekrementacja counter będzie atomowa. Trzeba pamiętać, że problemem staje się wiele funkcji bibliotecznych - np. free, malloc itd.


    Rozumiem, czyli temat niestety na dłużej niż pięć minut ;) . Ale naświetliłeś mi kiedunek poszukiwań, dzięki.

    Dodano po 8 [minuty]:

    zdziwiony napisał:
    Osobiście nie za bardzo widzę taki kod w C.Tak jak mirekk36 pisał w C takie coś to proszenie się o kłopoty.Ten numer przejdzie raczej tylko programie pisanym w asemblerze.A jak to zrobić? No tutaj muszę zdradzić straszne tajemnice ( AVRStudio datasheet jakiegoś AVR jakaś książka , net i trening i jeszcze raz trening... )


    Myślałem o jakimś działającym przykładzie - nie tyle do kopiowania co do analizowania i nauki.
    W datasheetach raczej bezpośrednio tego nie ma (nie wdepnąłem na przykład użycia).
    W necie obawiam się że kiepsko będzie, skoro to niepopularne podejście ;) ale poszukam.
    Nie ukrywam, że moja wiedza i znajomość sprzętu jest wybiórcza, taka jak mogę nauczyć się sam z dostępnych źródeł a potem doświadczalnie. Pewnie większość z Was zdobywa swoją wiedzę podobnie. Tylko ja ośmielam się zadać na elce ambitniejsze pytanie niż "jak zamigać ledką?" ;) więc nie traktujcie mnie jak chcącego wszystko na tacy.
    Zdecydowanym przeciwnikom przypominam, że wszystko co działa jest poprawne a zwycięzcy nie pyta się o racje :P . Więc piszemy dlaczego nie używać a każdy potem wybiera sam co zrobi a czego nie.

  • #32 02 Cze 2010 18:52
    atom1477
    Poziom 43  

    A co Cię konkretnie interesuje?
    Bo takie rzeczy jak podmienianie adresu powrotu to ja już robiłem. W BASCOMie :D

  • #33 02 Cze 2010 19:04
    zdziwiony
    Poziom 21  

    No proszę bardzo

    // Program skompilowany pod AVRStudio 4
    // To działa po dotknięciu int0 do plusa
    // a w praktyce to nawet po dotknięciu końcówką miernika

    .INCLUDE "m32def.inc"
    .org 0x0000
    rjmp Reset
    .org INT0addr // ustawienie wektora dla int0
    rjmp ob_przerw // -//-
    .org 0x2a
    Reset: //wektor dla reset tutaj skacze proc po resecie

    ldi R24,high(RAMEND)
    out SPH,r24 // ustawienie wskaźnika stosu
    ldi r24,low(RAMEND)
    out SPL,r24


    cli // zablokowanie przerwań

    in r24,WDTCR
    ori r24,(1<<WDTOE)
    out WDTCR,r24 // wyłączenie watchdoga coby nie przeszkadzał
    andi r24,~(1<<WDE)
    out WDTCR,r24

    ldi r24,0x3
    out DDRD,r24
    ldi r24,0x6 //konfiguracja portów
    out PORTD,r24 // świeci się jedna dioda PD1

    in r24,MCUCR
    ori r24,0x3
    out MCUCR,r24 // ustawienie przerwań int0
    in r24,GICR
    ori r24,0x40
    out GICR,r24
    sei // odblokowanie przerwań globalnych

    petla: //pusta pętla głównego programu
    rjmp petla
    //--------------------
    ob_przerw: // tutaj proc skacze po wywołaniu int0
    pop r24 // podnosimy ze stosu starszy adres
    pop r24 // podnosimy młodszy adres
    ldi r24,low(innapetla)
    push r24 // zapisujemy własny młodszy adres
    ldi r24,high(innapetla)
    push r24 // zapisujemy własny starszy adres
    reti // wracamy z przerwania ale już nie do głównego programu
    //----------------------------
    innapetla:
    ldi r24,0x5 // tylko tutaj
    out PORTD,r24 // Swieci się dioda PD0
    rjmp innapetla // po wywołaniu przerwania program kręci się w tej pętli

    Kod proszę umieszczać w znacznikach code!
    Robak

  • #34 02 Cze 2010 20:05
    tmf
    Moderator Mikrokontrolery Projektowanie

    Ale powiedz mi jaki jest sens tego kodu? Przecież to samo mogę osiągnąć bez podmiany adresu na stosie...
    PO. - powiedz jaki masz konkretnie problem, to coś się wymyśli. Bo mam wrażenie, że na siłę chcesz coś skomplikować, nawet jeśli to nie ma najmniejszego sensu.
    Co do goto to fakt, jest niekoszerne. ale też nie jest krótsze niż np. while(1). Zresztą nawet jeśli by było to w językach wyższego poziomu nie ma za wielkiego sensu wprowadzać takich optymalizacji - lepiej to zgłosić jako misoptimization bug do twórców kompilatora, po czym program przekompilować nowszą wersja :) Goto cieszy się złą sławą bo utrudnia śledzenie wykonywania programu, co jest wystarczającym powodem by go nie stosować (tu zapewne jak wszędzie też są wyjątki).

  • #35 02 Cze 2010 21:26
    mirekk36
    Poziom 42  

    tmf napisał:
    Ale powiedz mi jaki jest sens tego kodu?


    Sensu w ogóle nie ma, (sorka) ale to jest ambitny przykład na miarę ambitnych pytań, niestety. No bo , jakie kto stawia pytania, to....., takie dostaje odpowiedzi.

    Jeśli ten przykład miałby posłużyć tylko do tego, żeby zobaczyć jak podmienić adres powrotu na stosie, to jest to o tyle BEZ SENSU przykład, że o wiele prościej byłoby poczytać o tym jak działa stos - i to co opisywane jest jako sztuczka okazałoby się żadną tajemną wiedzą. Jak ktoś zrozumie jak działa stos (a to nie jest trudne) to takie operacje można porównać do zjadania przysłowiowej bułki z masłem. No ale jak ktoś woli od tylca - to już jego sprawa ;) będzie trzeba się dłużej i boleśniej uczyć na własnych błędach.

  • #36 03 Cze 2010 00:44
    rpal
    Poziom 27  

    ja się przy okazji przyłaczę bo kol. tmf pisał coś o niekoszerności. Aż się prosi zatem zapytać skoro goto jest takie naganne to po jakiego grzyba w ogóle jest zaszyte w kompilatorach. Z jednej strony krytyka użycia a z drugiej możliwość stosowania? Osobiście nie stronię od tej instrukcji choć bez jakiegoś większego do niej sentymentu. Co zaś tyczy się samego tematu to na mój gust jest bez sensu bo jeśli kolega autor (nic o tym nie pisał) nie ma możliwości śledzenia programu, to przy kolejnych zwisach i resetach programu urośnie mu siwa broda zanim załapie co było przyczyną zmasakrowania przerwania, lepiej jak wcześniej inni pisali skupić się na ich poprawności niż na zrobieniu wszystkiego aby się wykrzaczyły :)

  • #37 05 Cze 2010 13:50
    PO.
    Poziom 20  

    Moje pytania mają charakter ogólny a odpowiedzi, także Twoje, wyznaczają mi kierunki nauki. Ze stosem masz rację. Jak pisałem wyżej, dobrze jest poznać wszystkie metody, żeby wiedzieć które są dobre a które lepsze (a które złe :P ).

    Ad goto:
    Czy jeśli ktoś stosuje goto to świadczy to o tym, że:
    * jest megacieniasem bo robi to "po basicowemu"?
    * jest megamasterem bo robi to "po asemblerowemu"?
    I w jednym i w drugim języku istnieje instrukcja skoku i jest używana.
    A teraz wady w c:
    * zaciemnia przepływ programu - więc przy profesjonalnym pisaniu w zespole jest co najmniej nie wskazana, żeby sobie wzajemnie pracy nie utrudniać.
    * łatwiej o błąd - więc trzeba wiedzieć gdzie i jak ją stosować (mnie w ogrniczonym zakresie nie sprawia żadnych trudności i akurat przez goto się nie wykładam :D - odpukać - jak to o mnie świadczy, patrz wyżej :E ).
    * gorzej się optymalizuje - bo kompilatorowi trudniej śledzić program i go podzielić - ale tu sobie trochę strzelam. W c to ważne, przynajmniej na avr, bo ma świetną optymalizację. Z drugiej strony, np wieczna pętla na goto zajmuje najmniej (wynikowego kodu). Jak inne pętle, z obłsugą warunków, nie wiem, pewnie tu się robi podobnie - no i pytanie wtedy, ja
    k to wygląda po optymalizacji a nie przed.

    Sam prosiłbym o uwagi n/t goto, może coś pominąłem.
    Dla mnie to świetne rozwiązanie, ale nie zawsze oczywiście. No i ja piszę dla siebie, i po swojemu.
    Aha, switch to jest przecież warunkowe goto w bloku, tylko usankcjonowane ;) .


    Ja w tym temacie nie mam problemów - to znaczy chciałbym pociągnąć tu dyskusję ogólną, na poziomie wyższym niż podstawowy.
    O konkretne problemy pytam w innych wątkach. Może ktoś inny a jakiś ciekawy problem? Nie musimy się ściśle tytułu trzymać.


    PS: może coś o pisaniu optymalnego kodu? Ostatnio wydaje mi się, że mi wszystko "puchnie" (uprzedzając, to bez goto...) w porównaniu do tego co piszą inni - oceniając na podstawie ogólnie projektów bez wgłębiania się w szczegóły, bo często nie ma jak bezpośrednio porównać. Nawet po optymalizacji, 50% mniej, to i tak jest za dużo...

  • #38 05 Cze 2010 18:52
    tmf
    Moderator Mikrokontrolery Projektowanie

    rpal - goto jest bo mamy wolny wybór :) Pistolet też można kupić, od człowieka zależy co z nim zrobi. Poza tym są sytuacje w których goto może byc bardziej przejrzyste niż inne formy wyjścia z danego bloku programu (ale to raczej wyjątki).
    PO. - jeśli ktoś stosuje goto wtedy kiedy jest to najlepsze rozwiązanie to jest geekiem :) Kiedy stosuje jak popadnie i dlatego bo mu się wydaje, że jest to dobre to potrzebuje nauki.
    Co do switch to nie ma to nic wspólnego z goto - nigdzie nie występują dziwne skoki - switch działa w ramach bloku programu.
    Jeśli uważasz, że goto jest takie dobre to prześledź zoptymalizowany kod assemblerowy wygenerowany z progrmau w c, gdzie masz kilka warunków i pętli. Tam będzie mnóstwo instrukcji skoku, czasami wydawałoby się w dziwacznych miejscach. Jeśli to będzie dla ciebie tak samo czytelne jak kod w c to śmiało stosuj goto :) Normalnie po prostu nie ma potrzeby stosować tej instrukcji - pisze sobie właśnie program na PC, ma jakieś 30tys. linii kodu, ani jednego goto, nie dlatego, że jest niekoszerne - po prostu nie było potrzebne. Po części może to wynikać z faktu, że pisze w c++, a tam dzięki wyjątkom goto po prostu traci rację bytu - właśnie obsługa wyjątków to jest chyba jedyny racjonalny przykład użycia goto w c.

  • #39 05 Cze 2010 22:46
    utak3r
    Poziom 25  

    PO. napisał:
    No i ja piszę dla siebie, i po swojemu.


    Zmienisz podejście, gdy będziesz chciał po kilku miesiącach wprowadzić kilka zmian do swojego starego programu.

  • #40 05 Cze 2010 23:51
    PO.
    Poziom 20  

    utak3r napisał:
    PO. napisał:
    No i ja piszę dla siebie, i po swojemu.


    Zmienisz podejście, gdy będziesz chciał po kilku miesiącach wprowadzić kilka zmian do swojego starego programu.

    Akurat to mi nie sprawia problemu :) - za to trudno mi się czyta cudze kody. Chyba bez jakiegoś szczególnego powodu.

    Dodano po 14 [minuty]:

    tmf napisał:
    rpal - goto jest bo mamy wolny wybór :) Pistolet też można kupić, od człowieka zależy co z nim zrobi. Poza tym są sytuacje w których goto może byc bardziej przejrzyste niż inne formy wyjścia z danego bloku programu (ale to raczej wyjątki).
    PO. - jeśli ktoś stosuje goto wtedy kiedy jest to najlepsze rozwiązanie to jest geekiem :) Kiedy stosuje jak popadnie i dlatego bo mu się wydaje, że jest to dobre to potrzebuje nauki.
    Co do switch to nie ma to nic wspólnego z goto - nigdzie nie występują dziwne skoki - switch działa w ramach bloku programu.
    Jeśli uważasz, że goto jest takie dobre to prześledź zoptymalizowany kod assemblerowy wygenerowany z progrmau w c, gdzie masz kilka warunków i pętli. Tam będzie mnóstwo instrukcji skoku, czasami wydawałoby się w dziwacznych miejscach. Jeśli to będzie dla ciebie tak samo czytelne jak kod w c to śmiało stosuj goto :) Normalnie po prostu nie ma potrzeby stosować tej instrukcji - pisze sobie właśnie program na PC, ma jakieś 30tys. linii kodu, ani jednego goto, nie dlatego, że jest niekoszerne - po prostu nie było potrzebne. Po części może to wynikać z faktu, że pisze w c++, a tam dzięki wyjątkom goto po prostu traci rację bytu - właśnie obsługa wyjątków to jest chyba jedyny racjonalny przykład użycia goto w c.

    Nie całkiem kiedy popadnie. Są sytuacje, w których można by coś zrobić inaczej a mimo to stosuję goto bo jest mi łatwiej. Czasami to maniera a nie dużo łatwiej.
    Ale też nie sieję na lewo i prawo - zazwyczaj w ogóle nie używam. To raczej specyficzne konstrukcje/zastosowania, w których się pojawia. Na pewno też nie unikam histerycznie.

    Każdy kod bez goto jest bardziej przejrzysty, nie zawsze bardziej optymalny/krótszy/itp. Etykiety to świetnie ćwiczenie umysłu, tak nawiasem ;) . Polecam początującym z nadmiarem czasu, w jakimś programie testowym - i potem odplątywanie co nie działa i dlaczego - potem co i dlaczego jakoś tak przychodzi samo :) .
    Co do kodu asm to na razie sprawia mi problemy nie z powodu skoków tylko słabej znajomości asm ogólnie i "wczucia się" sprzęt.

    Dla mnie switch jest szalenie podobne - oczywiście jest "ustandaryzowane" i zachowuje się przewidywalnie, bo są narzucone ograniczenia.

    A wszystko zaczęło się od niewinnej uwagi o pętli głównej na goto :) - akurat główna zawsze jest wieczna, więc wszystko jedno na czym ją robić, oprócz tego że ostatnio przypadkiem mi wyszło, że na goto jest "najtaniej" pod względem oszczędności miejsca. Ale główną robię różnie, w zależności od fantazji.


    PS: to może ja zacznę o optymalizacji, skoro wszyscy tacy nieśmiali...
    Jak macie funkcje "przełączniki" w stylu włącz/wyłącz coś w zależności od parametru (jedna/kilka linijek kodu, np włącz/wyłącz timer), albo funkcje inicjalizacji czegoś (raz wywoływane i koniec, np zainicjalizuj parametry timera) to jak je piszecie? Może w ogóle nie funkcje tylko makra?

  • #41 06 Cze 2010 00:02
    utak3r
    Poziom 25  

    Jeśli chodzi o goto, to w C nie użyłem go ani razu - od 20 lat...

    A co do "makr", czyli funkcji inline - zależy od sytuacji. Jeżeli potrzebujesz funkcji, która jest krótka, a czas jej wykonania jest krytyczny - używasz inline. Jeżeli jednak czas nie jest aż taki krytyczny, nie robisz tego - zyskujesz wówczas rozmiar kodu mniejszy.

  • #42 06 Cze 2010 00:04
    gaskoin
    Poziom 38  

    PO. napisał:
    utak3r napisał:
    PO. napisał:
    No i ja piszę dla siebie, i po swojemu.


    Zmienisz podejście, gdy będziesz chciał po kilku miesiącach wprowadzić kilka zmian do swojego starego programu.

    Akurat to mi nie sprawia problemu :) - za to trudno mi się czyta cudze kody. Chyba bez jakiegoś szczególnego powodu.


    jak Twoje programy zaczna mieć po 7000 lini to zacznie Ci być trudno. Cudze kody źle się czyta z wiadomych przyczyn, ale wiele sie mozna przy tym nauczyc (stety, niestety - umiejac juz cos wczesniej). Funkcji goto w swoim dorobku nie uzylem tez ani razu

  • #43 06 Cze 2010 13:44
    PO.
    Poziom 20  

    Czytam i się uczę. I po to też jest ten temat ;) . A czego używać, niech każdy zdecyduje sam, nikogo nie zmuszam ani nawet nie namawiam.

    Jak robi się tyle linii to już rozbijam na pliki i includuję bo nie tyle się źle czyta co źle poprawia, za dużo skakania góra-dół :) .


    Pytam czego używacie i kiedy, i co (na co nie wpadłem) zastosować, żeby było najmniejsze np. Jak funkcja ma 1-2 linijki to niestety przechodzę na makro, właśnie przerabiam jeden projekcik eksperymentalnie i chudnie w oczach...
    Moja wiedza jest dość wybiórcza, może nie wiem czegoś oczywistego bo nie wdepnąłem przy nauce na cudzych kodach (i błędach) właśnie...

  • #44 06 Cze 2010 14:18
    tmf
    Moderator Mikrokontrolery Projektowanie

    Jeśli funkcja ma 1-2 linijki to możesz ją zrobić jako inline, albo lepiej wybrać stosowne opcje optymalizacji, tak że efekt będzie taki sam jak dla makra, albo i lepszy. Makra to zło w rękach osób niedoświadczonych a i doświadczonym potrafią nabruździć. Są neutralne względem typów - czyli kontrola typów właśnie wylatuje w powietrze, stwarzają kłopoty z ewaluacja wyrażeń arytmetycznych, np.:
    #define MAX(a, b) ((a) < (b) ? (b) : (a))
    int x = 5, y = 10;
    int z = MAX(x++, y++);

    Jaką spodziewasz się uzyskać wartość? Przekompiluj to, zdziwisz sie :)
    Coś prostszego:
    #define MULT(x, y) x * y
    int z = MULT(3 + 2, 4 + 2);
    A teraz co wg ciebie powinno wyjść?
    To tylko parę przykładów zła płynącego z makr, makra mają też pozornie dobre strony, co kusi żeby ich używać.
    Także jeszcze raz - zamiast uczyć się języka od sztuczek weź porządną książkę o c i zacznij od podstaw. Inaczej nigdy nie będziesz dobrze pisał programy. Każdy rozsądny programista powie ci, że sztuczek używa się wtedy kiedy absolutnie nie da się ich uniknąć, a nie przy normalnym pisaniu programów. Zresztą jak sam widzisz, mamy już 43 posty dokładnie o niczym.

    Dodano po 2 [minuty]:

    PO. napisał:
    Pytam czego używacie i kiedy, i co (na co nie wpadłem) zastosować, żeby było najmniejsze np. Jak funkcja ma 1-2 linijki to niestety przechodzę na makro, właśnie przerabiam jeden projekcik eksperymentalnie i chudnie w oczach...


    A po co ma być mniejsze? Mieści się w pamięci procesora? To git. Co ci z tego, że po wgraniu programu zostanie ci 40% wolnej pamięci?
    A BTW pokaż te twoje zabiegi odchudzające. Założę się o co chcesz, że wynikają one z błędnego kodu, a odchudzenie nie wymaga żadnych sztuczek.

  • #45 06 Cze 2010 15:02
    utak3r
    Poziom 25  

    PO. napisał:
    Jak robi się tyle linii to już rozbijam na pliki i includuję bo nie tyle się źle czyta co źle poprawia, za dużo skakania góra-dół :) .


    Nie no, oczywiście - ale to kompletnie nic nie zmienia.

    tmf napisał:

    A BTW pokaż te twoje zabiegi odchudzające. Założę się o co chcesz, że wynikają one z błędnego kodu, a odchudzenie nie wymaga żadnych sztuczek.


    Zgadzam się w pełnej rozciągłości, również obstawiam, że owe "odchudzanie", to po prostu doprowadzanie do postaci, w jakiej powinno być od razu ;)
    Poza tym - uważaj, nie wpadnij w pułapkę... nie zawsze odchudzenie programu z objętości jest dobre - zwłaszcza dla... wydajności.

  • #46 07 Cze 2010 02:07
    PO.
    Poziom 20  

    Mieści się bo zawsze biorę nadmiarowego procka :) . Ale ogólnie nie jestem zadowolony z wyników, czytam co Wam wychodzi... I na logikę czasami wychodzi za dużo "niczego" to znaczy mały pogram szybko rośnie a potem już przestaje i trzyma poziom. Muszę czegoś za dużo dodawać na początku ;) .

    Takich makr nie stosuję. W pierwszym z powinno być 10 a w drugim 30 - przynajmniejm mam wrażnie że taka była intencja programisty ;) .

    Czy temat jest o niczym? Dla mnie nie jest. Książkę? Z książki mogę się dowiedzieć jak coś działa ale nie nauczę się programować - algorytm to zawsze ścieżka myślenia a nie kopiuj/wklej :E . No dobra, jakie książki polecasz?

  • #47 07 Cze 2010 06:15
    atom1477
    Poziom 43  

    Może i taka była intencja, ale wyjdzie 11 i 13.
    Co nie znaczy że makra są złe. Tmf podał podchwytliwy przykład, ale większość przykładów podchwytliwych nie jest.

  • #48 07 Cze 2010 07:36
    94075
    Użytkownik usunął konto  
  • #49 07 Cze 2010 11:37
    tmf
    Moderator Mikrokontrolery Projektowanie

    atom1477 napisał:
    Może i taka była intencja, ale wyjdzie 11 i 13.
    Co nie znaczy że makra są złe. Tmf podał podchwytliwy przykład, ale większość przykładów podchwytliwych nie jest.


    Brawo :) Mój przykład nie jest specjalnie podchwytliwy, każde makro z argumentami stwarza tego typu problemy. Wynika to z tego, że przyzwyczajeni jesteśmy w c do ewaluacji argumentów przed wywołaniem funkcji, a makra tak nie działają. Więc tego typu błędy są naturalne. Oczywiście to, że pisze, że makra są złe nie znaczy, że nie wolno ich używać. Są sytuacje (w c, nie C++), w których ich użycie jest sensowne. W przeciwieństwie do wcześniej drążonego goto wielokrotnie używam makr we własnych programach.

  • #50 07 Cze 2010 13:09
    atom1477
    Poziom 43  

    Ja bym w takim powiedział że w takim razie C rodzi niezdrowe przyzwyczajenia (te do ewaluacji argumentów). Sory, ale C to nie same zalety. I chyba znalazłem wadę :D Oczywiście trochę żartuję.

  • #51 07 Cze 2010 13:32
    utak3r
    Poziom 25  

    Ależ wcale nikt nie powiedział, że język stworzony 30 lat temu jest idealny :) - bo nie jest. Jest natomiast niezłym wyborem, gdy chodzi o programowanie mikrokontrolerów - zwłaszcza tych mniejszych.

  • #52 07 Cze 2010 13:45
    atom1477
    Poziom 43  

    Nie no żartowałem. Wiadomo że C ma wady. Choćby takie że w nim nie ma obiektów (dla mnie to akurat żadna wada :D). Po to w sumie powstało C++.
    A ten przykład tmf-a to dobry. Myślałem że wystarczy nawiasy odpowiednio pododawać ale nie.
    Zawsze jak zadziała z "x++" to nie zadziała z "x + y". I odwrotnie.

  • #53 07 Cze 2010 13:52
    utak3r
    Poziom 25  

    atom1477 napisał:
    Po to w sumie powstało C++.


    Dokładnie tak: to są dwa różne języki, które mają dwa różne targety :) Do jednego projektu lepiej nada się C, do innego C++.
    Szkoda tylko, że są tak bardzo do siebie podobne, co powoduje niestety ciągłe ich mylenie i "kfiatki" w stylu programów napisanych w C ze składnią C++... ech. Ale dość offtopu :)

  • #54 08 Cze 2010 15:55
    PO.
    Poziom 20  

    Trochę sobie na mnie poużywaliście w sąsiednim wątku...
    Więc prostując: nie "lubię" makr tylko ostatnio próbuję się na nie przesiąść żeby skompresować kod (kompilowany a nie pisany oczywiście).
    Nie używam makr z argumentem poza bit value; jakiekolwiek makra z argumentem byłyby bez sensu bo i tak sprowadzałyby się do użycia dodatkowego warunku powiekszającego kod. W związku z tym są oddzielne makra na włącz i na wyłącz, co może jest nieładne ale skuteczniejsze.
    Nawet makra bit value nigdy nie używam z argumentem wyliczeniowym, zawsze ma znany stały argument liczbowy albo ukryty pod nazwą rejestru z datasheeta - czyli też stały.

    Fakt, przykład z makrami dał mi do myślenia i przypomniał przed czym się pilnować. Przypominam natomiast tym, którzy mnie nie znają ;) albo zapomnieli: nigdy nie robię czegoś, co nie wiem jak działa

  • #55 08 Cze 2010 16:05
    utak3r
    Poziom 25  

    PO. napisał:
    Nie używam makr z argumentem poza bit value; jakiekolwiek makra z argumentem byłyby bez sensu bo i tak sprowadzałyby się do użycia dodatkowego warunku powiekszającego kod.


    No nie do końca - odpada kod związany z obsługą stosu przy wołaniu funkcji i powrocie z niej (a może jeszcze np. przełączanie stron flasha itp.).


    PO. napisał:

    nigdy nie robię czegoś, co nie wiem jak działa


    No i tak trzymać :) Ale oczywiście poznawać, jak tutaj.

  • #56 08 Cze 2010 16:18
    PO.
    Poziom 20  

    utak3r napisał:
    PO. napisał:
    Nie używam makr z argumentem poza bit value; jakiekolwiek makra z argumentem byłyby bez sensu bo i tak sprowadzałyby się do użycia dodatkowego warunku powiekszającego kod.


    No nie do końca - odpada kod związany z obsługą stosu przy wołaniu funkcji i powrocie z niej (a może jeszcze np. przełączanie stron flasha itp.).


    To prawda, będzie mniej. Ale bez warunku będzie jeszcze mniej :) . Wzięło mnie na ambicję ostatnio - moje przejrzyste i wygone w pisaniu programy są nieoptymalne objętościowo :( .

  • #57 08 Cze 2010 16:18
    tmf
    Moderator Mikrokontrolery Projektowanie

    PO. napisał:

    Więc prostując: nie "lubię" makr tylko ostatnio próbuję się na nie przesiąść żeby skompresować kod (kompilowany a nie pisany oczywiście).


    Mam propozycję, pokaż kod, który kompresujesz makrami, a ja obiecuję ci, że zrobię to bez makr, tak samo efektywnie i być może bardziej elegancko :)

    BTW, makra bez argumentów też mogą dać w kość :) Kolejne przykłady?:)

  • #58 08 Cze 2010 16:59
    PO.
    Poziom 20  

    Prosty przykład, zamiana:

    Code:

    void timer0ovf_on(uint8_t on){
     if(on) TIMSK0 set1 b(TOIE0);
     else TIMSK0 set0 b(TOIE0);
    }

    na:
    Code:

    #define timer0_ovf_1 TIMSK0 set1 b(TOIE0);
    #define timer0_ovf_0 TIMSK0 set0 b(TOIE0);

    Kompilator sobie tego nie optymalizował - znaczy zawsze była różnica, mimo wartości argumentu znanej przy kompilacji.
    Wiem, mógłbym to pisać niby bez makr ale nazwy rejestrów są mniej przyjazne i kod potem nieczytelny.

    Oprócz tego muszę dojść, co jeszcze kosztuje mnie dużo w kodzie. Może generalnie nadużywam funkcji - tylko zawsze myślałem, że kompilator podejmie lepszą decyzję i w razie czego włączy ciało funcji w kod zamiast wywoływać. Szczególnie, że sporo funkcji mam bez parametrów.

  • #59 08 Cze 2010 18:46
    mirekk36
    Poziom 42  

    To nie prościej byłoby tak?

    Code:
    #define timer0_ovf_ON    TIMSK0 |= (1<<TOIE0)
    
    #define timer0_ovf_OFF   TIMSK0 &= ~(1<<TOIE0)


    Każda z tych linijek zamieni ci się na pojedynczy rozkaz asm. Krócej już się nie da tego skompilować.

    Dodano po 21 [minuty]:

    No tak tylko sam zobacz, że do tak prostego makra ty zapodajesz jeszcze 26 tysięcy innych makr w makrach i wyjść mogą przez to później dziwolągi, szczególnie właśnie przy podstawianiu parametrów.

    u ciebie w zapisie:

    Code:
    TIMSK0 set1 b(TOIE0); 


    musi być w tym makrze jeszcze rozwinięte makro set1 i jakieś kolejne makro b(param)

    zresztą czy chce ci się pisać, tzn wyżej definiować jeszcze całe stado takich makr jak set1, set0 czy b(). Przecież jeśli już wspominasz o lepszej czytelności kodu to moim zdaniem wygodniej byłoby zrobić makra (jeśli w o góle warto byłoby je robić)

    set i reset zamiast set1 i set0

    no ale to już tylko taka kosmetyka, bez jakiegoś szczególnego wpływu na program. Raczej tylko i wyłącznie na czytelność, bo jak widzę set1, set0 to domyślam się, że mogę gdzieś dalej trafić na set2, set3 albo i set847.

    Dodano po 3 [minuty]:

    Przyznam szczerze, że kiedyś jak przechodziłem z pascala na C to też nagminnie definiowałem sobie makra set i reset ;) bo były dla mnie bardziej czytelne na początku. A teraz? .... teraz bardziej czytelne są operatory |= czy &= ~ itp

  • #60 08 Cze 2010 19:53
    tmf
    Moderator Mikrokontrolery Projektowanie

    PO. napisał:

    Oprócz tego muszę dojść, co jeszcze kosztuje mnie dużo w kodzie. Może generalnie nadużywam funkcji - tylko zawsze myślałem, że kompilator podejmie lepszą decyzję i w razie czego włączy ciało funcji w kod zamiast wywoływać. Szczególnie, że sporo funkcji mam bez parametrów.


    Co do makr to Mirek już napisał co i jak więc nie będę się powtarzał. Co do funkcji to generalnie jeśli zdefiniujesz je z atrybutem inline to efektywnie będą się one zachowywały jak makra - kompilator zamiast generować skok do takiej funkcji będzie włączał jej ciało w miejscu gdzie się do niej odnosisz (tyle, że nie będziesz miał w/w problemów z argumentami). Domyślnie tak robi dla małych funkcji. Warto też pomyśleć nad atrybutami const i pure przy deklarowaniu funkcji, co ułatwi kompilatorowi optymalizację. Podobnie jak warto deklarować przy przekazywaniu parametrów przez referencję dany argument jako const, jeśli funkcja go nie zmienia. No ale znowu - to wszystko znajdziesz w książkach, np. wspomnianej biblii C.