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.

[STM32][C] - Poprawne pisanie własnych bibliotek

wojlej 06 Lip 2016 23:01 8271 83
  • #61 06 Lip 2016 23:01
    wojlej
    Poziom 17  

    :shocked!:

    Dzięki :)

    Dzięki Panom JacekCz i tadzik85 wiem, że takie pisanie to złe pisanie. Gdyby stos nie był wystarczająco duży mógbym pisać po niechcianych fragmentach pamięci (chociaż i tak tak na prawdę to robiłem). Dzięki i daje pomógł :)

  • #62 06 Lip 2016 23:24
    Freddie Chopin
    Specjalista - Mikrokontrolery

    wojlej napisał:
    Freddie, czy porównywałeś ten sam kod napisany w C i w C++ pod kątem rozmiaru zajmowanej pamięci, szybkości działania? Jeśli tak to jestem ciekaw wyników

    Kod o identycznej funkcjonalności będzie identycznie szybki.

    Szybkość pisanego kodu jest mitem. Większość osób zapewne nie używa C++ bo jest wolny, ale używa HAL/SPL dla STM32 i tutaj nagle nie ma problemu szybkości...

    Twój problem należy rozwiązać podając do funkcji przez argument zewnętrzny bufor wraz z jego rozmiarem i tyle. Nic lepszego nie wymyślisz i szkoda czasu na kombinacje. Jeśli bufor jest zbyt mały to funkcja zwraca błąd.

  • #63 06 Lip 2016 23:54
    grko
    Poziom 33  

    Cytat:

    Globalne (ale nie wątkowe, niektóre funkcje formatujące tak działają), albo jakiś rodzaj zarządzania tymi fragmentami pamięci. W C jest to hardkor, bardzo trudno to eksploatować (łatwo raz użyć źle). Tym niemniej profesjonalny kod w C (linux, drivery itd) potrafi alokować w jednym module, a gdzieś zupełnie inaczej zwolnić (kosztem bardzo precyzyjnego i podatnego na zapomnienia kodu)

    W obiektowym C++ czy standardowe typy stringowe (std::string, ale i wynalazki innych mutacji C++), lub drugie to "sprytne pointery". Zasadniczo dla takich algorytmów najważniejsze, czego nie ma w C, to automatyczne destruktory, przydatna jest też hermetyzacja obiektów, i gwarantowana inicjacja przez "profesjonalnie" zrobiony konstruktor. Wtedy takie pisanie jest możliwe, bezpiecznie i wygodne.

    Nawiasem mówiąc, kliniczny przykład że "C++ jest wolniejsze". Nie jest wolniejsze ani na takt, ale implementacja zwracania automatycznie zarządzanych obiektów jest o wielokroć ambitniejsza *)
    To jest takie miejsce, gdzie religijne trzymanie się C nie potrafi się obronić, ale z religią nie ma dyskusji.


    Naprawdę, Twoje posty powoli robią się żałosne. Naprawdę musisz zaznaczać w każdym wątku wyższość C++? Odniosę sie tylko do dynamicznej alokacji pamięci. Z twojego posta wynika, że przez te wszystkie fajne mechanizmy w C++ nie ma wycieków pamięci. Życie pokazuje, że jest dokładnie odwrotnie.

    Odniosę się równiez do std::string. Nie mam nic przeciwko tej klasie (ani samemu C++). Jednak religijne przekonanie, że to jest tak samo szybkie jak operacje na null terminated strings jest śmieszne. Warto jednak zdawać sobię sprawę jakie są koszty użycia tej klasy:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Pierwszy przykład z internetu. Dodałem jeszcze volatile do wskaźników przy null-terminated strings. Rezultat testu jest chyba wiadomy. Zastanówmy się jakim "performance killerem" będzie uzycie tej klasy w krytycznym miejscu przykładowo w taki sposób:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dodajmy do tego ilu tak naprawdę programistów zdaje sobie z tego sprawę. Jeszcze raz zaznaczam, nie mam nic przeciwko tej klasie ani C++. Jednak warto sobie zdawać sprawę jakie są koszty pewnych udogodnień. Dobranoc.

  • #64 07 Lip 2016 08:43
    Freddie Chopin
    Specjalista - Mikrokontrolery

    GrzegorzKostka napisał:
    Warto jednak zdawać sobię sprawę jakie są koszty użycia tej klasy:

    No dobra, ale wiesz że przykład którym się posłużyłeś nie ma identycznej funkcjonalności, no nie? <: Nie żebym był za używaniem std::string na mikrokontrolerach w każdej sytuacji, no ale jednak wypadałoby zaznaczyć, że ta klasa ma sporo większe możliwości niż goły wskaźnik. Bo gdyby Twój przykład zrobić "tak jak należy" w C++, czyli użyć std::swap(), to różnica maleje... Zacznijmy jednak od tego, że Twój przykład na dzień dobry wywala dwa poważne ostrzeżenia:

    Kod: bash
    Zaloguj się, aby zobaczyć kod


    Jeśliby je poprawić, to od razu zaczyna być widać czym się różni jedno użycie od drugiego - albo trzeba używać "const char*" (ups, teraz tych "null-terminated strings" już nie zmodyfikujesz), albo trzeba używać tablic i je kopiować przy użyciu memcpy() (jak wyczarować uniwersalnie rozmiar tablicy dla g?) albo trzeba mieć dodatkowe wskaźniki które kopiujesz, co pokazuje jak bardzo bezsensowny jest ten przykład (na std::string też można mieć wskaźnik i sobie go kopiować - wtedy różnica będzie oczywiście zerowa). No ale idźmy po najmniejszej linii oporu, czyli opcja pierwsza. Oryginalny przykład pokazuje "slowdown" rzędu 20. Zmieniam na std::swap() (kompiluję w standardzie C++11) i już jest slowdown 3. A wciąż przypominam, że w tych dwóch pętlach funkcjonalność _NIE_ jest taka sama, ponieważ stringi możemy sobie potem modyfikować jak chcemy, a "const char*" już niezbyt. To wszystko przy optymalizacji zero, bo w każdym innym przypadku optymalizator "zje" ten test, ponieważ jest on tak słaby. No ale powiedzmy że do stop() dorzucę uniwersalną barierę w postaci:

    asm volatile ("" ::: "memory");

    Włączam optymalizację -O2 i "slowdown" wynosi już AŻ 1.12723... ups... zaczyna wyglądać na to, że std::string jednak nie jest taki zły...

    Idąc dalej, Twój "performance killer" powinien wyglądać tak:

    Code:
    std::string foo3;
    
    foo3.reserve(foo1.size() + foo2.size() + sizeof("123"));
    foo3 += foo1;
    foo3 += "123";
    foo3 += foo2;


    Wtedy już nie byłby taki "killer", no ale gorzej by wyglądało jako argument o wyższości gołych wskaźników nad std::string (; Dynamiczną alokację też można by ominąć, ale to już wyższa szkoła jazdy...

    Danego języka trzeba umieć używać. Ja też mogę wymyślić jakiś bzdurny i bezsensowny przykład w C który będzie okrutnie wolny i czego to dowodzi? Po prostu C jest proste i każdy go zna, wiec praktycznie każdy by od razu widział, że taki kod jest po prostu źle napisany i stąd problem. C++ jest zaś bardzo bardzo (aż za bardzo) skomplikowany, mało kto go zna w stopniu większym niż absolutne podstawy, stąd w Twoim przykładzie mało kto dostrzeże źródło problemu i potencjalne rozwiązania. Wtedy łatwo powiedzieć, że to C++ jest problemem, a nie ten kto napisał bzdurny kod porównujący przysłowiowe "jabłka i pomarańcze".

    To są takie przykłady jakby wziąć ciężarówkę STAR oraz Lamborghini i udowadniać że STAR jest zawsze lepszy od tego drugiego bo przez las i po piachu spokojnie przejedziemy z prędkością 40kmph i to jeszcze z dwoma tonami ładunku...

  • #65 07 Lip 2016 09:33
    JacekCz
    Poziom 36  

    GrzegorzKostka napisał:


    Naprawdę, Twoje posty powoli robią się żałosne. Naprawdę musisz zaznaczać w każdym wątku wyższość C++? ...

    Odniosę się równiez do std::string. Nie mam nic przeciwko tej klasie (ani samemu C++). Jednak religijne przekonanie, że to jest tak samo szybkie jak operacje na null terminated strings jest śmieszne. Warto jednak zdawać sobię sprawę jakie są koszty użycia tej klasy:
    ....
    Dodajmy do tego ilu tak naprawdę programistów zdaje sobie z tego sprawę. Jeszcze raz zaznaczam, nie mam nic przeciwko tej klasie ani C++. Jednak warto sobie zdawać sprawę jakie są koszty pewnych udogodnień. Dobranoc.


    Spierasz się ze mną w różnych watkach, wnosząc wartość merytoryczną i to prawda. Natomiast wielokrotnie polemizowałeś z poglądami których nigdy nie wypowiedziałem. Ponosi Cie zmysł polemiczny.

    Tutaj od razu powiedziałem że std:string jest wolniejszy - ale ma o wiele ambitniejszy zamiar. Żeby plastycznie powiedzieć: tyle mają sobie wspólnego w/s przenoszenia wartości ciągów literowych, co kierowca z pizzerii punktowany minutowo naruszający przepisy ruchu drogowego skuterkiem, z firmą pocztową wiozącą wiele (zaplombowanych) przesyłek poleconych.

    Pytanie w pełni uzasadniało panoramiczne naświetlenie jakie możliwości zwrotu "nie-prostych" wartości ma język.

    Dodano po 11 [minuty]:

    Freddie Chopin napisał:

    Twój problem należy rozwiązać podając do funkcji przez argument zewnętrzny bufor wraz z jego rozmiarem i tyle. Nic lepszego nie wymyślisz i szkoda czasu na kombinacje. Jeśli bufor jest zbyt mały to funkcja zwraca błąd.


    O!!! I to jest prawdopodobnie jedna z najlepszych odpowiedzi w duchu C.
    Są i takie w bibliotece standardowej. Zmusza użytkownika API do świadomego obsłużenia pamięci, ale uwalnia od tego funkcję.

    Mają też mutację (popularną w Win API - proszę nie polemizować, że syfiaste API itd bo złote czy bezbłędne to ono nie jest) pierwsze wywołanie z inaczej podanymi argumentami "oblicz mi długość bufora którą będę potrzebował" i drugie "a teraz mi zwróć wartość o czym negocjowaliśmy"

  • #66 07 Lip 2016 09:35
    grko
    Poziom 33  

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Tak, tam ma być const char *. Tak jak pisałem, to przykład z Internetu, który odpaliłem o godzinie 24 ;)

    Odnośnie rozwiaząnia problemu wydajności to oczywiście masz racje i to:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    rozwiązuje problem. Teraz powiedz mi ilu tak naprawdę programistów zdaje sobie z tego sprawę a ilu napisze po prostu:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Cytat:

    Danego języka trzeba umieć używać. Ja też mogę wymyślić jakiś bzdurny i bezsensowny przykład w C który będzie okrutnie wolny i czego to dowodzi? Po prostu C jest proste i każdy go zna, wiec praktycznie każdy by od razu widział, że taki kod jest po prostu źle napisany i stąd problem. C++ jest zaś bardzo bardzo (aż za bardzo) skomplikowany, mało kto go zna w stopniu większym niż absolutne podstawy, stąd w Twoim przykładzie mało kto dostrzeże źródło problemu i potencjalne rozwiązania. Wtedy łatwo powiedzieć, że to C++ jest problemem, a nie ten kto napisał bzdurny kod porównujący przysłowiowe "jabłka i pomarańcze".


    Zgadzam się w 100%. Trzeba dobrze znać język który się używa. Nie znam dobrze C++ i nie wiem co może powodować problemy z wydajnością. Wydaje mi się, że takich miejsc jest więcej niż w C. W C wszystko jest na tyle proste, że od razu rozumiem kod, który czytam i wiem gdzie mogą być potencjalne problemy z wydajnością. Chyba zgodzisz się, że bezkrytyczne wychwalanie C++ jest trochę irytujące? Zwłaszcza w co drugim poście w tematach nawet nie związanych z C++.


    Cytat:

    Spierasz się ze mną w różnych watkach, wnosząc wartość merytoryczną i to prawda. Natomiast wielokrotnie polemizowałeś z poglądami których nigdy nie wypowiedziałem. Ponosi Cie zmysł polemiczny.


    Ty za to musisz dorzucić swoje fantazje na temat C++ i jego wyższości nad C do 50% swoich postów. Bardzo merytoryczne, naprawdę.

  • #67 07 Lip 2016 09:47
    JacekCz
    Poziom 36  

    Freddie Chopin napisał:
    Bo gdyby Twój przykład zrobić "tak jak należy" w C++, czyli użyć std::swap(), to różnica maleje...


    Są pewne testowe pętle na stringach, które pokazują że C++ jest dużo wolniejsze od Javy (w rzeczywistości nieoptymalnie użyte). Z realnym kodzie ... hmmm... jeden z nich jest trochę wolniejszy/trochę szybszy. Jak powiedziałem "alokowac może małpa, zwolnić mistrz". Tam przyjęli odśmiecanie jako strategię.

    Jest pewien serwer (message broker więc wszystko ambitnie) zaimplementowany zarówno w C++ jak i Javie, nie podejrzewam aby ktoś świadomie/podświadomie wstawiał nieoptymalności pod udowodnienie czegoś. W każdym razie wersja C++ nie bardzo chce dorównać szybkością Javie (chyba jest lepszy w szczytowym zużyciu RAM w porywach). Wersji C nie ma, brakło by osobolat na zarządzanie pamięcią ;)

    Dodano po 51 [sekundy]:

    Freddie Chopin napisał:
    argument o wyższości gołych wskaźników nad std::string


    Wielu na początku zadaje sobie pytanie, czy podobna klasa stringowa nie dałaby się zrobić wiele prościej. Otóz aby to zrobić, trzeba jednocześnie osiągnąć wiele celów.

    Jako szczeniak sobie wymyśliłem "wrapper na char*" i ulepszałem go wiele miesięcy (po czym porzuciłem). Np startując nie uświadamiałem sobie że wejściowy, inicjujący napis może pochodzić ze stałych alokowanych statycznie, zmiennych statycznie, alokowanych czy ze stosu, czyli innym model pamięci. Jeden po wykorzystaniu możesz zwolnić, drugi musisz zwolnić, trzeciego nie wolno zwalniać...

  • #68 07 Lip 2016 10:51
    Freddie Chopin
    Specjalista - Mikrokontrolery

    GrzegorzKostka napisał:
    Teraz powiedz mi ilu tak naprawdę programistów zdaje sobie z tego sprawę a ilu napisze po prostu:

    To jest problem poboczny - nie świadczy on o języku tylko co najwyżej o jego popularności czy średnim stopniu zaawansowania jego użytkowników (; Po prostu trzeba być świadomym tego co się robi - czy to w C, czy w C++, czy w czymkolwiek innym. W jednym języku osiągnięcie takiej świadomości może być trudniejsze niż w innym, ale to że coś jest bardziej skomplikowane nie znaczy że jest gorsze. Przykładowo mikrokontrolery 32-bitowe są bardziej skomplikowane niż te 8-bitowe, elektronika cyfrowa - bardziej niż instalacja elektryczna w kuchni, a całkowanie - bardziej niż mnożenie. Wraz z większymi możliwościami idą - niestety - większe ilości wiedzy które trzeba przyswoić.

    "With great power comes great responsibility." (;

    GrzegorzKostka napisał:
    Chyba zgodzisz się, że bezkrytyczne wychwalanie C++ jest trochę irytujące?

    Wiadomo (; Niemniej jednak bezkrytyczne i często błędne (jak choćby w przykładzie który znalazłeś) najeżdżanie na C++ (to piszę ogólnie) jest równie irytujące (;

  • #69 07 Lip 2016 19:49
    alagner
    Poziom 25  

    Cytat:
    Po prostu trzeba być świadomym tego co się robi - czy to w C, czy w C++, czy w czymkolwiek innym. W jednym języku osiągnięcie takiej świadomości może być trudniejsze niż w innym, ale to że coś jest bardziej skomplikowane nie znaczy że jest gorsze. Przykładowo mikrokontrolery 32-bitowe są bardziej skomplikowane niż te 8-bitowe, elektronika cyfrowa - bardziej niż instalacja elektryczna w kuchni, a całkowanie - bardziej niż mnożenie. Wraz z większymi możliwościami idą - niestety - większe ilości wiedzy które trzeba przyswoić.


    A od siebie dodam, że jak możesz policzyć 2piR to nie całkujesz. Ergo jeżeli ten bezmyślny
    Kod: c
    Zaloguj się, aby zobaczyć kod
    działa i się mieści w ramie/flashu/czasie wykonania to go zostawiasz i masz gdzieś dopóki nie przeszkadza. Jeżeli zaczyna - profilujesz. Nie chodzi oczywiście o bezkrytyczny zachwyt nad wszystkimi "ficzerami" C++, ale pamięć jest do używania, nie do bycia pustą.

  • #70 07 Gru 2016 23:27
    wojlej
    Poziom 17  

    Próbuje napisać coś w stylu klasy ale stanąłem w miejscu. Klasa ma obsługiwać usart. W pliku H zadeklarowałem strukturę która przechowuje m.in. wskaźniki na funkcje, a w konstruktorze do tych wskaźników przypisuje funkcje.

    Plik h

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Plik C
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Test plik Main
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Problem jest w funkcji SendByte. Tam dane trzeba wpisać do rejestru DR danego USARTA. Czy jest jakiś mechanizm który pozwoli mi z poziomu tej funkcji sprawdzić parametry obiektu (struktury USART_class) który wywołal tę funkcję? Chodzi oczywiście o język C

  • #71 07 Gru 2016 23:51
    2675900
    Użytkownik usunął konto  
  • #72 07 Gru 2016 23:53
    Freddie Chopin
    Specjalista - Mikrokontrolery

    1. Po co wynajdywać koło od zera? Nie prościej użyć C++? Gwarantuję Ci, że efekt będzie co najmniej identyczny pod względem szybkości i rozmiaru, a całkiem możliwe że szybszy i mniejszy. Kod oczywiście będzie krótszy i bardziej niezawony.
    2. W C++ obiekt klasy jest przekazywany jako ukryty argument do funkcji. Ty próbujesz zrobić odwrotnie, czyli z obiektu wywoływać funkcję przez wskaźnik. To po prostu trzeba zrobić odwrotnie.

  • #73 12 Gru 2016 19:16
    wojlej
    Poziom 17  

    Jeżeli chodzi o C++, to czy ma On jakieś wady w systemach wbudowanych? Np, jak wygląda działanie na stringach. STM nie ma MMU, więc w jaki sposób odbywa się coś takiego:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Czy jeżeli na stringa jest malocowana pamięć to znaczy że muszę ją zwolnić?
    free(txt);

    Nie wiem czy jasno się potrafię wyraźić. Niech ktoś mi przedstawi wady C++.
    [/code]

  • #74 12 Gru 2016 19:52
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Mieszasz różne sprawy. To czy dany układ ma MMU czy go nie ma jest bez znaczenia dla klasy takiej jak std::string. Ona po prostu wewnętrznie zarządza pamięcią którą sobie sama wewnętrznie zaalokowała dynamicznie. MMU jest zupełnie zbędne z punktu widzenia C++ (czy jakiegokolwiek innego "kompilowalnego" języka bez cudów typu garbage collector).

    Niemniej jednak, czy jak zaczynamy dyskusję o C++, to od razu pierwsze co jest istotne to std::string? Piszę te projekty na mikrokontrolery tylko w C++ już od dobrych kilku lat i naprawdę ani razu nie użyłem std::string...

    Wady w systemach embedded może mieć tylko i wyłącznie Twój kod i rzeczy które w nim użyjesz. To czy napiszesz je w C czy w C++ jest bez znaczenia - kiepski (wolny/duży/błędny/niebezpieczny/...) kod można napisać w każdym języku. Niektórzy twierdzą, że łatwiej zrobić to w C++, ale raczej na takiej zasadzie, że zakładają iż ktoś tego języka nie zna. Tyle że jak ktoś nie zna zwykłego C to też mu będzie łatwiej napisać kiepski kod w C. Z drugiej strony łatwiej się uszkodzić wiertarką elektryczną niż wiertarką ręczną, ale jakoś nie widać zwolenników używania tylko narzędzi ręcznych... With great power comes great responsibility.

    Niemniej jednak jeśli wymagasz dokładnie tego co oferuje std::string na mikrokontrolerze, to użycie dokładnie tej klasy będzie i tak lepszą opcją niż napisanie zbliżonej funkcjonalności w C (pomijamy oczywiście drobny szczegół, że jest to praktycznie niemożliwe ze względu na brak destruktorów). Zwykle jednak na mikrokontrolerze nie jest potrzebne dokładnie to co oferuje std::string - można zupełnie dobrze obejść się ze statycznymi buforami na stosie czy nawet globalnymi, unikając problemów dynamicznej alokacji pamięci (które nie są specyficzne dla żadnego języka, choć w C++ bardziej popularne).

    Da się pisać programy w C++ na mikrokontrolery bez "new", std::string, std::vector itd. Ma to nadal sens, bo nawet bez tych rzeczy działają funkcje wirtualne, ściślejsza kontrola typów, template'y, enkapsulacja, konstruktory/destruktory i inne rzeczy które są albo "darmowe", albo ich overhead jest pomijalnie mały w obliczu korzyści jakie dają (RAII).

  • #75 12 Gru 2016 19:59
    2675900
    Użytkownik usunął konto  
  • #76 12 Gru 2016 20:13
    wojlej
    Poziom 17  

    Głównie piszę w C, generalnie widzę u siebie ogromny postęp. Mam wrażenie że gdybym spotkał siebie rok wcześniej to dałbym sobie w pysk za kod który pisałem wtedy. Teraz pisze bardziej hermetycznie. Na pewno jest wiele do poprawy ale w C poruszam się całkiem sprawnie. Dlaczego pytam o string? Bo większość moich projektów polega na komunikacji tekstowej i w C po prostu malocuje bufory char. Dodatkowo czasem coś skubnę w C#, jakąś apkę pomocniczą, np komunikująca się z przyrządami pomiarowymi po GPIB.
    Od pewnego czasu zastanawiam się nad przejściem do C++ własnie z racji dużej obiektowości, możliwości przeciążania operatorów lub choćby przeciążania metod. Podoba mi się, że mogę ukryć działanie klasy metodami prywatnymi. Oczywiście w C też mogę opatrzyć je słowem kluczowym static ale to nie to samo bo IntelliSens i tak je podpowiada, co powoduje że przy rozbudowanym projekcie i kilkudziesięciu parach plików c i h muszę dbać o nazewnictwo funkcji. W C++ mogę zrobić je prywatne. Podoba mi się, że inicjalizację UARTU mogę zrobić już w konstruktorze, a o interfejsach już nie wspomnę.....
    Generalnie fajnie tylko nie widzę wad tego języka w systemach wbudowanych, a wolałbym być ich świadom.

    Dodano po 3 [minuty]:

    P.S. Spojrzałem w pierwszy lepszy projekt. Plik odpowiadający za aktualizację oprogramowania przez BLE - 467 linii. A to i tak niewielka część projektu.

  • #77 12 Gru 2016 20:19
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Po prostu przejdź na C++ i już. Nie ma żadnych wad, a 99% tego co możesz przeczytać w necie to durne przesądy leśnych dziadków. Kod o tej samej funkcjonalności w C czy w C++ będzie działał identycznie w obydwóch przypadkach. Tyle że ten w C++ będzie krótszy, prostszy (powiedzmy że to kwestia subiektywna) i zapewne bardziej odporny na błędy.

    Ja też się bardzo długo nosiłem z myślą przejścia na C++. Jak w końcu to zrobiłem, to nie zrobiłem już nigdy żadnego projektu w C.

    Jedyne co można uznać za wadę ogólną to fakt, że C++ po prostu jest bardziej skomplikowany od C, a programowanie obiektowe jest bardziej skomplikowane niż programowanie proceduralne z milionem zmiennych globalnych (obstawiam że to najpopularniejszy sposób organizacji projektów na mikrokontrolery).

    Niemniej jednak wiele rzeczy o których piszesz nie są wcale takim świetnym pomysłem jak Ci się wydaje. Np. używanie dynamicznej alokacji pamięci na układzie z małą ilością RAM może łatwo zaowocować taką fragmentacją pamięci, że po prostu niczego nie zaalokujesz, choć niby jeszcze pełno pamięci jest wolnej. Inicjalizacja czegokolwiek bardziej skomplikowanego w konstruktorze tez nie jest takim super pomysłem, bo z konstruktora nie ma jak zwrócić błędu (poza rzucaniem wyjątkami - również niezbyt dobry pomysł na mikrokontrolerze), a do tego przy globalnych obiektach narażasz się na wpływ kolejności wywołania konstruktorów w różnych plikach - bardzo łatwo się na to "nadziać", a bardzo trudno potem znaleźć przyczynę problemu.

  • #78 12 Gru 2016 20:24
    tadzik85
    Poziom 38  

    Freddie Chopin napisał:
    Ja też się bardzo długo nosiłem z myślą przejścia na C++. Jak w końcu to zrobiłem, to nie zrobiłem już nigdy żadnego projektu w C.


    To może przygotowałby kolega dla potomności przykład ? Bez rtosa dla uproszczenia?

  • #79 12 Gru 2016 20:27
    wojlej
    Poziom 17  

    Ja zmiennych globalnych staram się nie używać. Mój pierwszy projekt to mnóstwo externów. Jak zacząłem się w tym gubić to stwierdziłem, że to chyba nie tędy droga. Teraz każda para plików c i h odpowiada za konkretną rzecz. Ewentualnie includuje inne i odpowiada za większą konkretną rzecz. Każdy mój plik ma dwie zmienne typu static. Pierwsza to numer Major do mojego rejestratora błędów, a druga to struktura z danymi które chce na zewnątrz udostępnić. Jest jeszcze zawsze funkcja zwracająca wskaźnik na tą strukturę. To rozwiązanie się bardzo dobrze sprawdza. A w C++ nie musiałbym takich rzeczy robić.

  • #80 12 Gru 2016 20:28
    Freddie Chopin
    Specjalista - Mikrokontrolery

    tadzik85 napisał:
    To może przygotowałby kolega dla potomności przykład ? Bez rtosa dla uproszczenia?

    No ale co w tym przykładzie by miało być (innego niż w przykładzie dla C)? Przykłady ze stronki - choć już nieco "przedatowane" - spokojnie nadają się do wrzucenia do nich kodu C++. Jakby się uprzeć to miganie LEDem można zrobić w C++, ale zaraz by się pojawili malkontenci co by udowodnili, że przecież jakby to zrobić w C to by było 3x szybsze i 2x mniejsze. Ustawianie PLL w C czy w C++ będzie identyczne - funkcja i tyle. No chyba że idziemy w extremum i stworzyć magiczny template który wyliczy parametry PLL w czasie kompilacji - jest to zapewne możliwe, ale osoby o słabszych nerwach mogłoby przyprawić o zawał (;

  • #81 12 Gru 2016 20:31
    tadzik85
    Poziom 38  

    Freddie ja się w całości z tobą zgadzam. Jednak prostu uart i2c coś prościutkiego gdzie jednak pokazane jest ze to C++ a nie C napisany z C++. Od dłuższego czasu wspierasz C++ z czym się zgadzam ale dla większości ludzi uwierzyć znaczy zobaczyć...........

  • #82 12 Gru 2016 20:36
    wojlej
    Poziom 17  

    Nawet nie uwierzyć, żeby zobaczyć. Ale chodzi o takie wskazówki jak napisałeś wcześniej, żeby np nie używać knstuktora do inicjalizacji - ja myślałem że on jest idealnie do tego stworzony...
    Jeżeli możesz to wrzuć jakąś bibliotekę (pracującą z peryferialami) którą możesz udostępnić, po to żeby popatrzeć.

  • #83 12 Gru 2016 20:52
    2675900
    Użytkownik usunął konto  
  • #84 12 Gru 2016 20:53
    Freddie Chopin
    Specjalista - Mikrokontrolery

    tadzik85 napisał:
    Freddie ja się w całości z tobą zgadzam. Jednak prostu uart i2c coś prościutkiego gdzie jednak pokazane jest ze to C++ a nie C napisany z C++. Od dłuższego czasu wspierasz C++ z czym się zgadzam ale dla większości ludzi uwierzyć znaczy zobaczyć...........

    Trzeba by to przemyśleć (razem z aktualizacją przykładów), tylko ten brak czasu... Ehh...

    wojlej napisał:
    Ale chodzi o takie wskazówki jak napisałeś wcześniej, żeby np nie używać knstuktora do inicjalizacji - ja myślałem że on jest idealnie do tego stworzony...

    Idealnie do momentu w którym nie musisz obsłużyć żadnego błędu (; Jeśli nie ma możliwości błędu i nie używasz żadnego innego globalnego obiektu który też ma konstruktor - problemu nie ma.

    wojlej napisał:
    Jeżeli możesz to wrzuć jakąś bibliotekę (pracującą z peryferialami) którą możesz udostępnić, po to żeby popatrzeć.

    W podpisie masz link - distortos to RTOS napisany w całości w C++11. Od kilku miesięcy jest tam też HAL napisany w sposób obiektowy - jest np. uniwersalna klasa SerialPort używająca interfejsu UartLowLevel oraz implementacja tegoż interfejsu w postaci klasy ChipUartLowLevel.

    https://github.com/DISTORTEC/distortos/blob/m...istortos/devices/communication/SerialPort.hpp
    https://github.com/DISTORTEC/distortos/blob/m...r/source/devices/communication/SerialPort.cpp
    https://github.com/DISTORTEC/distortos/blob/m...tortos/devices/communication/UartLowLevel.hpp
    https://github.com/DISTORTEC/distortos/blob/m...1/include/distortos/chip/ChipUartLowLevel.hpp
    https://github.com/DISTORTEC/distortos/blob/m...ls/USARTv1/STM32-USARTv1-ChipUartLowLevel.cpp

    Kod: c
    Zaloguj się, aby zobaczyć kod