Rynek pracy STM32

Janusz <janusz snipped-for-privacy@o2.pl napisał(a):

O jakie konkretnie szablony Ci chodzi? Te z C++ polegają na tym, że kompilator tworzy kilka wersji jednej funkcji. Są normalnym kodem i na AVR będą siedzieć we Flashu a nie RAM-ie. Nie ma dynamicznie generowanego kodu w czasie działania programu.

Reply to
Grzegorz Niemirowski
Loading thread data ...

W dniu 2022-07-21 o 13:09, Grzegorz Niemirowski pisze:

No właśnie o tym cały czas piszę :) nic te szablony czy polimorfizmy nie dają w np zmniejszeniu ilości kodu. Przejrzystości też nie.

Reply to
Janusz

Janusz <janusz snipped-for-privacy@o2.pl napisał(a):

Zmniejszają kod źródłowy, wynikowy oczywiście nie.

Reply to
Grzegorz Niemirowski

W dniu 2022-07-21 o 13:36, Grzegorz Niemirowski pisze:

No właśnie, przy małych prockach z małymi zasobami jest to istotna wada. Dlatego cały czas piszę że nie da się jednej miary przykładać do wszystkiego, środowiska z dużych maszyn nijak sie mają do małych procków, ale herby zaraz na mnie nakrzyczy że jestem betonem i jest inaczej :)

Reply to
Janusz

W dniu 2022-07-21 o 12:53, Janusz pisze:

Janusz, sorry, ale dzielnie bronisz pozycji nie do obrony.

Kluczowe słówko: 'bo'. Kwestia nie wykonywania z RAMu była użyta tylko jako wytłumaczenie dlaczego do głównej tezy, że program wygenerowany z templates nie pójdzie w avr. Chodzi o prawdziwość/nie prawdziwość tej głównej tezy a nie użytego argumentu za nią.

Skojarzenie.... Kiedyś (+- 1990) potrzebowaliśmy aby 8751 'wykonywał' program ze swojego RAMu (128 bajtów). Zrealizowaliśmy to jako interpreter programu pisanego w opracowanym przez nas języku na bazie języka Forth (opiera się na odwrotnej notacji Polskiej). Interpretacja pojedynczego rozkazu średnio zajmowała 10us (rozkaz maszynowy zajmował 1us).

Oczywiście brat napisał ten interpreter ale wszystkie programy w tym Forth pisałem ja. Czyli każdy z programów musiał być zapisany na mniej niż 128 bajtach (no bo jeszcze stos procesora i dane).

To były programy do programowania poszczególnych GALi różnych producentów (każdy rozmiar GALa * każdy producent to osobny program) i do programowania poszczególnych EEPROMów szeregowych (I²C, SPI, microWire i kilku innych). W ten sposób załatwiliśmy to, że mogliśmy rozszerzać gamę programowanych elementów bez konieczności upgradeowania oprogramowania (w tamtym czasie konkurencyjne programatory wymagały w tym celu odesłania do producenta).

Bardzo dokładnie musiałem panować nad RAMem - gdy program ładował pierwszy blok danych do programowania to zazwyczaj niszczył swój początek. Rozmiar używanego w danym programie bloku danych dobierałem tak, aby zniszczenie nie sięgnęło głównej pętli. Liczba bajtów potrzebna na stos procesora zależała od treści mojego programu (ile zagłębień pętli) i uwzględniałem to w poczatkowym ustawieniu wskaźników.

Wiem, że już kiedyś na p.m.e to pisałem, ale siła skojarzenia z "nie wykonuje programu z ram-u". P.G.

Reply to
Piotr Gałka

Piotr Gałka snipped-for-privacy@cutthismicromade.pl napisał(a):

Pójdzie, bo szablony C++ nie mają nic wspólnego z wykonywaniem kodu z RAM-u.

Reply to
Grzegorz Niemirowski

Nie wykona. Nie musi. Szablony "nie są w ramie". Metody wirtualne też nie.

Dostałeś dwa przykłady, na oba przypadki, działajace na AVR, napisane w kilka minut.

Reply to
heby

To zależy. Nie da się jednoznacznie tak powiedzieć. Wynikiem przeciętnego zastosowania szablonu w codziennej pracy jest *lepiej* zoptymalizowany kod. Więc zależy od użycia a nie ogolnie od bycia lub nie, szablonem.

Reply to
heby

Rzecz w tym, że nie masz pojęcia o czym mówisz. Więc to nie beton. To takie inne słowo.

Reply to
heby

Widziałem te twoje wypociny, daruj sobie.

Więc to nie beton. To

Dalej wycieczki osobiste?

Reply to
Janusz

W dniu 2022-07-20 o 23:08, heby pisze:

Ścisłych, pozytywnych bohaterów (ale nie ma tam głównego bohatera) miała też książka "Niezwykłe perypetie odkryć i wynalazków", ale to nie była beletrystyka tylko literatura faktu.

To wiem. Ale mógłbyś mieć więcej tolerancji gdy ktoś się walnie i potem nie umie się z tym pogodzić.

Ja uważam, że są dwa poziomy pewności: - jestem pewny, - jestem absolutnie pewny.

Jeśli jakaś dyskusja jest prowadzona tak, że można cokolwiek jednoznacznie powiedzieć tylko w przypadku absolutnej pewności to dyskusja jest bardzo trudna bo ktoś, kto coś wie jedynie na poziomie 'jestem pewny' nie powinien się odzywać, albo musi swoją wypowiedź otoczyć szeregiem zastrzeżeń podających w jakich aspektach ma wątpliwości co do przedstawianych faktów. Zaletą takiej dyskusji jest to, że można zakładać, że wszystko co się usłyszało jest 100% pewne, ale wadą, że można zgubić kluczowe informacje bo będą przemilczane.

Znacznie prostsze jest dyskutowanie, gdy również w stanie jedynie 'jestem pewny' można po prostu krótko powiedzieć 'to jest tak a tak'. Wszyscy, którzy coś wiedzą się odezwą, żadnych informacji się nie pominie bo ktoś nie absolutnie pewny nie przemilczy swojej wiedzy. Ale uczestnicy muszą wtedy świadomie przykładać do wszystkich wypowiedzi jakiś poziom ufności (rzędu 95% - czyli jedna na 20 wypowiedzi może zawierać błąd).

Ja do wszystkich informacji, które widzę na p.m.e przykładam te 95%. Również do Twoich wypowiedzi, choć wiem, że jesteś raczej z tego pierwszego rodzaju dyskusji. Dzięki temu nie mam żadnego problemu z tym, że ktoś się pomyli nie ze złej woli tylko po prostu wypowiedział się na podstawie pewności a nie absolutnej pewności.

Nie zwracam mu uwagi w sposób, który wywołuje odruch obronny prowadząc stopniowo do przepychanek.

Uważam, że jestem urodzonym dydaktykiem. Miałem co najmniej dwie okazje się o tym 'prawie jednoznacznie' przekonać, ale nie miejsce tutaj na rozpisywanie się jeszcze o tym.

Wczoraj wieczorem (czyli koło 1-ej w nocy na spacerze) doszedłem do wniosku, że chyba mam rację, że mi się to niewiele przyda, bo ja niewiele piszę, ale mój brat prawie 100% pracy poświęca na pisanie. Muszę kiedyś (miesiąc, dwa) pogadać z nim o tym i przekonać, że to może być dobre. Wtedy jako najlepszą drogę widzę jakbym najpierw ja to ogarnął.

Ja myślę, że z embedded jest jednak trochę bardziej skomplikowanie niż się Tobie wydaje (na podstawie Twoich wypowiedzi). Brat niedawno nie zostawiał suchej nitki na jakimś przykładowym programie USB dla tego Silabsa. Jak pisałeś o metodach znanych od lat

80-tych oddzielenia kodu od hardware'u to miałem wrażenie, że ten program co mu się tak bardzo nie podobał to pewnie był napisany według tych metod. Niestety kompletnie za mało wiem, aby cokolwiek bardziej jednoznacznie powiedzieć.

Nie mam pojęcia czy dotykam dobrego punktu, ale takie skojarzenie. Wydaje mi się (podkreślam wydaje mi się), że w niektórych prockach nie można odczytać portu, zmienić jednego bitu i zapisać z powrotem bo w ten sposób można zmienić stan innego bitu, który akurat chwilowo był wymuszony z zewnątrz. I jak przez mgłę pamiętam sprzed lat, że brat coś takiego mówił, przy spotkaniu z jakimś programem, że jakiś idiota ma swój kawałek do którego przydzielone są np. 3 nogi i program pisze tak, jakby pozostałych nóg nie było. Pewnie użył jakąś bibliotekę gdzie ktoś zdefiniował jakąś abstrakcję obejmującą te 3 linie i ma w dupie co się dzieje naokoło - Jak można tak pisać !! A przypuszczam (znów tylko przypuszczam) że próba tworzenia abstrakcji tak aby jakieś rzeczy sprzętowe były od strony głównego programu zawsze takie same może prowadzić właśnie w tym kierunku. Oczywiście, zapewne ktoś coś tam źle podłożył łącząc to coś z tym akurat prockiem.

Bardzo prawdopodobne. Nie raz śledzę jakąś dyskusję w ogóle się nie odzywając i czasem coś sobie zanotuję bo a nuż się przyda więc dokładnie to samo można podejrzewać o innych śledzących p.m.e P.G.

Reply to
Piotr Gałka

W dniu 2022-07-21 o 14:23, Grzegorz Niemirowski pisze:

Nie wiem jak to skomentować. Czy ja aż tak niejasno piszę, że można podejrzewać, że to ja twierdzę, że nie pójdzie. P.G.

Reply to
Piotr Gałka

W dniu 2022-07-21 o 14:23, Grzegorz Niemirowski pisze:

Szablony tak, ale polimorfizm dynamiczny już nie, tzn pójdzie bo będzie de fakto statyczny czyli stałe procedury wygenerowane na każdą okoliczność wsadzone w rom. Tyle że ten sam efekt osiągam pisząc sobie sam specjalizowane funkcje na każdy rozdzaj argumentu, więc po co sie kopać z koniem czyli kompilatorem i wymyślać mu szablony czy przeciążenia argumentów? Co ma sens dla dużych procków i zespołów ludzi niekoniecznie ma sens dla małych i pojedynczych autorów.

Reply to
Janusz

To *jest* polimorfizm dynamiczny, kiedy kod *jest* wygenerowany przez kompialtor ,a całośc procesu sterowania nim odbywa sie przez indirect call.

Myslisz to z "kodem dynamicznym" albo "kodem samomodyfikującym" który nie ma z tym nic wspólnego.

Już to napisałem, ale najwyraźniej nie dociera.

Nawet na dużych komputerach używanie samomodyfikującego się kodu jest niewskazane i nikt tego nie robi powszechnie z jednym wyjątkiem: niektóre implementacje trampolin.

Działajacy na AVR przykład z polimorfizmem dynamicznym dostałeś na tacy. Działa, bo nie ma nic wspólnego z kodem samomodyfikującym.

Nie rozumiesz sensu szablonów.

Bywa, że wynikiem skomplikowanego kodu w szablonach jest *nic*. Albo 1 liczba. Albo gigabajt kodu. Wkładasz szablony do worka "dużo" bo nigdy w życiu ich nie używałeś do czegokolwiek. Po prostu wydaje Ci się, że dużo kodu źrłodłwego musi wygenerować dużo asemblera. A tu jest czasami odwrotnie.

Reply to
heby

Piotr Gałka snipped-for-privacy@cutthismicromade.pl napisał(a):

Spoko, już jasne.

Reply to
Grzegorz Niemirowski

W dniu 2022-07-21 o 15:06, Janusz pisze:

Nie wiem co się dokładnie kryje pod pojęciem polimorfizmu dynamicznego, ale funkcje wirtualne w kasach w C++ to na tyle na ile to rozumiem to zawsze są generowane na każdą okoliczność i wkładane do programu nawet jak jest to program na komputer a nie na mikrokontroler. Chyba, że kompilator widzi, że żaden obiekt danej klasy pochodnej nigdy nie jest tworzony to wtedy takie opisane w kodzie źródłowym funkcje tej kasy mogą nie wejść do programu wynikowego.

W okolicy 1990 nie znając jeszcze C++ pisałem (mały zespół - 1 ludź) program do naszego programatora GALi (ten sam co opisałem jego wnętrze z Forth) i tak bardzo potrzebowałem wołania pod tą samą nazwą różnych funkcji bo najpierw się wybierało rodzaj programowanego obiektu, a potem dla każdego były wywoływane te same funkcje (programu, odczytaj, skasuj, blankcheck) które dla każdego trzeba było inaczej zrealizować że zaimplementowałem to za pomocą wskaźników na funkcje.

Jak potem po raz pierwszy czytałem o C++ (mój pierwszy kontakt to książka Stroustrupa z 91 roku w oryginale) to widząc funkcje wirtualne pomyślałem - dokładnie to było mi potrzebne.

Więc nie zgodzę się z Tobą, że pewne rzeczy pozwalające czytelniej napisać program są tylko dla dużych. Ale nigdy nie nauczyłem się używać templates. One jakoś są dla mnie mniej czytelne niż klasy. P.G.

Reply to
Piotr Gałka

Przyjmuje do wiadomości.

Zakładałeś, że mógł nie zrozumieć idei?

Codziennie muszę walczyć z takim podejściem w sobie: wydaje mi się że to jest źle napisane. Ale jednoczesnie wiem, nie pisali tego idioci. Na sam koniec zazwyczaj okazuje się, że nie rozumiałem i jak zrozumiałem, to już się takie nie wydaje.

Ten pierwszy odruch "przeciez to jest źle!" należy w sobie zdusić ;)

Tutaj dam ci kontrprzykład:

Taki kod: Foo = 1<<BAR;

Jaką masz pewnośc, że BAR to numer bitu a nie wartość binarna bitu? Obie to int. Obie się skompilują.

Ktoś może powiedzieć: ale to trzeba wiedzieć!

Nie. Kiedy pisałem sporo kodu pod SAM7, programiści z Atmela mieli bardzo swobodne metody na nazywanie wartości binarnych i numerów bitów i

*nigdy* nie było wiadomo. Czarę goryczy przelały pliki konfiguracyjne do cpu, gdzie raz było #define BAR 16 a w innym, podobnym, #define BAR 4 (najwidoczniej ktoś poprawił).

Ten problem da się rozwiązać za pomocą C++ i szablonów. W taki sposób, że błedne użycie NIE będzie możliwe. Kod szablonowy będzie dośc długawy, ale na sam koniec będziesz to widział u siebie jako Foo |= BAR; lub podobnie. Ba, nie będzie się dało pomylić rejestru, flagi będa przypisane do konkretnego.

Czy to dobrze?

Okazuje się że nie.

Przychodzi embedowiec, widzi te wszystkie "debilizmy z templates" i biadoli ile to kodu w CPU zjada i dlaczego nie działa z Harvardem.

A zjada 0 Flasha. Tak naprawdę, to "kod templaetowy" wykonuje się na etapie kompilacji, jako metajęzyk.

... po czym miesiąc szuka kodu, w którym pomylił flagę.

Czasami ciezko pojąć, że ludzie wkręcają śrubki młotkiem, ale tak to wygląda z mojej perspetkywy.

Reply to
heby

I co, nie działają?

Reply to
heby

W dniu 2022-07-21 o 14:17, Piotr Gałka pisze:

Bo to co robi kompilator na avr to jest proteza, skoro nie da się kodu modyfikować podczas wykonania to robimy kody na każdy argument, osobne. Więc niby masz narzędzie ale de fakto to samo miałeś wcześniej pisząc sobie sam funkcje. Narzędzie jedynie 'ukrywa' przed tobą typ argumentu, wołasz raz a kompilator sam dobiera ścieszkę. W '86 nie trzeba takich protez robić bo kod może być zmieniany podczas wykonania programu.

czyli zrobiliście maszynę wirtualną.

Reply to
Janusz

W dniu 2022-07-21 o 15:34, heby pisze:

Mógł. Bo dopiero pierwszy raz widzi cokolwiek na ten procesor. Ale ogólnie to chyba mniej więcej ogarnął co autor miał na myśli. Ta rozmowa była ponad tydzień temu. Od tamtej pory cały czas się grzebie w tym i mam mu nie przeszkadzać, bo czas nas goni. Niestety akurat w kwestii USB tak mało wiem, że nie potrafię nic szczegółowo. Jak lata temu czytałem specyfikację USB (wtedy jeszcze nie było 3) to nie wyobrażałem sobie to ogarnąć. Od strony komputera jakoś łączę się z naszymi urządzeniami z naciskiem na 'jakoś'.

Przy okazji takie pytanie o przykład. Jakieś 5 lat temu próbowałem rozwiązać jakiś mój problem z GUID i poległem. Problem polega na tym, że nie jestem pewien o co chodziło więc mogę źle napisać.

Ja normalnie robię tak, że klasa urządzenia USB ma funkcję statyczną wyszukującą urządzenia tego typu.

Dokładnie wygląda to tak (przepisuję ręcznie z drugiego komputera):

int Usb485::FindDevs() { GUID g= {0x42C884DE, 0xCC54, 0x4014, {0x88, 0x99, 0xAA, 0xBB, 0xCC,

0xDD, 0xEE, 0xFF}}; return DevTab.FindDevs(g); } 88,99,... to fałszywe wartości

Próbowałem w jakiś inny sposób definiować ten GUID - jako ciąg bajtów - chyba nie byłem w stanie.

Chciałem móc przekazać GUID jako parametr konstruktora - chyba mi się nie udało.

Tak na prawdę to nie wiem co chciałem i na czym poległem (za dawno było). Pamiętam jedynie, że wniosek był - tylko tak to mi działa.

Wiedząc jak robię czasem inne klasy to zapewne:

- chciałem mieć klasę bazową, która ma GUID jako parametr konstruktora.

- ona ma funkcję FindDevs która korzysta z tego guid z konstruktora.

- konstruktor klasy pochodnej woła konstruktor klasy bazowej wpisując tam znany już w tym miejscu swój guid.

- klasa pochodna ma dostępną funkcję FindDevs klasy bazowej i ona umie użyć tego guid wpisanego w jej konstruktorze.

To chyba jest to, co mi się nie udało i w każdej klasie pochodnej mam jej własną statyczną FindDevs.

Nie pamiętam, gdzie się pojawia problem. Jakiekolwiek próby najwcześniej poniedziałek Dziś jeszcze nie wziąłem się za dokończenie płytki, która dziś mam skończyć, a jutro jest wyjątkowy dzień - coś załatwiamy i nie będzie czasu.

Od lat 90-tych widuję te foo i bar i nigdy nie wiem co o tym sądzić. Skąd się to wzięło i jak o tym mysleć.

Na razie o ile wiem to według brata przykład USB na załatwienie prostej rzeczy zabiera 10x za dużo miejsca i nie zostaje miejsca na naszą aplikację, a chcemy się zmieścić w 1/2 flasha z powodu upgrade'ów. P.G.

Reply to
Piotr Gałka

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.