Gdzieś między Polską a Niemcami, a szczególnie w NRD

Czas nieutracony (1) – Wstęp

Trzy lata to sporo czasu, uzasadnione jest pytanie co ja właściwie robiłem, że nie miałem czasu nawet na naprawienie bloga. Bardzo chętnie o tym opowiem, opowieść będzie dłuższa. Czas nie był zmarnowany, stąd tytuł (zapożyczony oczywiście). I uprzedzam z góry, że cykl będzie zawierać spore elementy autoreklamy 🙂 No i pewnie wykorzystam to, co tu piszę jako pierwszy szkic szkicu moich przyszłych prezentacji.

Zacznijmy od tego, że praca w branży samochodowej nie zaspokaja mojej potrzeby kreatywności. Typowy projekt w tej branży to implementacja dokładnych requirementów klienta. Nieważne jak dobre są twoje pomysły, trzeba spełnić requirementy i już. Niektóre z tych requirementów są negocjowalne, ale dotyczy to raczej zbyt wygórowanych wyobrażeń klienta co do tego, co jest możliwe. Nowa funkcjonalność, albo znaczące zmiany w zdefiniowanej funkcjonalności mają przyzerowe szanse na akceptację przez klienta.

W związku z tym można coś tworzyć jedynie w architekturze, implementacji i toolingu. Z tym że z tym toolingiem to też nie tak prosto - w korpo jest specjalny dział, który zajmuje się toolingiem i przeforsowanie swoich pomysłów na skalę większą niż aktualny projekt jest mało realne.

Mój pierwszy projekt w automotive robiłem około roku 2001 (Headunit AUDI C6, to ta skrzyneczka ze szczeliną na CD i przyciskami, ta w głębi).

Małe stanowisko testowe elektroniki do Audi A6

Małe stanowisko testowe elektroniki do Audi A6

Cały nasz zespół był nowy w tej działce, musieliśmy nauczyć się mnóstwa rzeczy, jak to się robi w automotive. A robi się tak:

  • Większość kawałków do automotive to są rzeczy real-time (zainteresowanym radzę nie czytać hasła z polskiej wiki, bo bez sensu jest) - znaczy muszą reagować w czasie nie dłuższym niż zdefiniowany. W większości wypadków nie ma żadnego GUI.
  • Jeżeli jakieś GUI jest (na przykład cluster, navi czy HUD), to typowo rozdziela się część real-time i część od GUI. Znaczy każda z tych części ma osobny core procesora (każdy core może być totalnie inny), albo mieć swój procesor.

Dalej skupimy się na tej części niegraficznej - bo jednak ta grafika to jest w nielicznych kawałkach elektroniki samochodowej. Więc te kawałki niegraficzne:

  • Są podłączone do jakiegoś busa, zazwyczaj CAN. No i oczywiście muszą obsługiwać komunikację w dwie strony i z wymaganiami (teraz wiele telegramów jest E2E protected i/lub szyfrowanych)
  • Ponieważ to jest real-time, to musi w tym chodzić regularny multitasking, z przerwaniami oczywiście też.
  • Każdy kawałek zapamiętuje swoje błędy, czyli musi mieć pamięć nieulotną.
  • Ostatnimi czasy w to wszystko wchodzi poważne security z kluczami publicznymi i prywatnymi, certyfikatami, Certificate Authority itd.
  • Część z tych kawałków jest istotna dla bezpieczeństwa i w tym momencie wchodzą wymagania functional safety, z wszystkimi tego konsekwencjami.
  • Używany sprzęt jest bardzo różny, procesory użyte w kolejnych projektach mogą się różnić wszystkim, nawet byte orderem, i trzeba o tym pamiętać przy kodowaniu.
  • Językiem w którym to się pisze jest najczęściej C, znacznie rzadziej C++ (to raczej przy tych częściach z GUI, ale nie tylko).
  • Niemal każde urządzenie jest produkowane w różnych wariantach, na przykład do różnych modeli samochodów, albo może używać przykładowo wyświetlaczy od różnych producentów. W związku z tym, kod zawiera mnóstwo konstrukcji #ifdef #else #endif.
  • Programiści pecetowi nie zdają sobie tego sprawy, ale w embedded pamięć występuje w wielu rodzajach w jednym systemie. Pecet ma RAM i już - w embedded mamy szybki RAM, wolny RAM, szeregowy RAM, video RAM, code FLASH, data FLASH, EEPROM, RAM z podtrzymaniem, ..., każdy rodzaj ma inne właściwości, prędkość, sposób dostępu ... . I przy każdym obiekcie musimy powiedzieć, w której pamięci on ma wylądować. I pilnować, żeby się zmieściło. Do tego bywa że na przykład, że dostęp do adresów nieparzystych jest o wiele wolniejszy niż do parzystych, i trzeba to uwzględniać.
  • Przy programowaniu na pececie operujemy na abstrakcjach sprzętu. Mechaniczny wyłącznik ma na pececie stany wyłączony i włączony, a w embedded musimy uwzględniać na przykład drgania styków. Innego sprzętu to też dotyczy - trzeba uwzględniać całą fizykę stojącą za sprzętem.
  • O, fizyka - pamięci EEPROM/FLASH mają ograniczoną ilość zapisów, które są w stanie znieść, i trzeba liczyć, czy to wystarczy na planowany czas życia samochodu. W Tesli dowiedzieli się o tym dopiero niedawno i musieli zrobić recall na sto kilkadziesiąt tysięcy samochodów z wymianą sprzętu, bo coś bez umiaru pisało logi do flasha.
  • W pececie nie musimy martwić się zasilaniem - ono po prostu jest. W samochodzie musimy uwzględniać, że napięcie zasilania może być zbyt niskie lub zbyt wysokie (chwilowo lub trwale), i odpowiednio reagować.
  • Podobnie z temperaturą - jak urządzenie robi się za gorące, trzeba reagować (na przykład wyłączając coś, co się grzeje).
  • I tak można jeszcze długo - w automotive praktycznie nie występują programiści po "normalnej", pecetowej informatyce. Niemal wszyscy są po studiach mniej lub bardziej związanych z elektroniką, informatycy którzy tu czasem trafiają wkrótce uciekają z krzykiem.
  • Używany procesor nigdy nie jest za mocny - zawsze jest dobrany tak sknersko, że trzeba się nagimnastykować żeby się wyrobił. Podobnie pamięci nigdy nie ma za dużo.

Dla porządku jeszcze trochę o kawałkach z GUI:

  • GUI zazwyczaj chodzi na derywatach UNIXa, z klasycznym POSIXowym API.
  • Część graficzna ma często podłączony jakiś mocniejszy bus, na przykład Ethernet albo MOST.
  • Języki programowania są tu różne, najczęściej to C++, ale widziałem na przykład projekt w Javie.

Jeszcze jakieś 10 lat temu, każda z firm robiących te kawałki prawie wszystko robiła sama - udział standardowego kodu był znikomy. Projekty dla różnych klientów przez jedną firmę miały często tą samą funkcjonalność robioną całkiem inaczej, reusability było niewielkie. To jest oczywiście koszt i potencjalne ryzyko, więc większość wiodących firm samochodowych i główni poddostawcy zawiązali w roku 2002 konsorcjum, które miało ten stan rzeczy zmienić. Nazwano to AUTOSAR. Założenia AUTOSARa omówię w następnej notce, a potem dojdę do miejsca, w którym wkraczam do gry 🙂

-----------------------------------------------------------------------------------------------------------------------

Dotyczy:

Kategorie:Programowanie

Sledz donosy: RSS 2.0

Wasz znak: trackback

-----------------------------------------------------------------------------------------------------------------------


5 komentarzy do “Czas nieutracony (1) – Wstęp”

  1. charliebravo pisze:

    O, blog powrócił, fajnie!

    @”w embedded pamięć występuje w wielu rodzajach w jednym systemie. Pecet ma RAM i już”

    Eee, no nie. Tzn, zgoda co do tego, że przeciętny programista na pececie nie dotyka specjalnych rodzajów pamięci. No ale przeciętny programista na pececie to teraz pisze w Javascripcie wewnątrz Chrome’a, lub podobnie.

    Mam doświadczenia i z pecetami (pewnie obaj mamy na myśli typową architekturę Intela pod Windowsem), i z embedded/mobile. To właśnie typowa architektura embedded czy mobile (powiedzmy i.mx6, Apple Ax czy inny SoC z telefonu) ma jeden blok pamięci RAM, i do tego „przylutowane są” wszystkie chipy. CPU, GPU, akceleratory video i 2d.

    To powoduje że wiele zadań (np. streaming tekstur do GPU, albo sprzętowa dekompresja video) robi się łatwiejsza, bo to ta sama pamięć, co najwyżej czasem trzeba martwić się o adresy wirtualne vs fizyczne (DMA-capable, continuous memory, takie szczegóły).

    Tymczasem „na pececie” takie na przykład GPU ma fizycznie blok własnej pamięci, „widoczny” przez szynę PCI-E czy innego NVlinka, i samo wysłanie tam danych efektywnie potrafi się robić bardzo nietrywialne (vide asynchroniczne transfery danych w CUDA, przy użyciu pinned memory).

    @Różne rodzaje pamięci
    Polecam GPU compute. Register file, device memory, shared memory, local memory, constant memory, texture memory…do wyboru do koloru. A użyj jednej z nich nie tak jak trzeba, wydajność spadnie o czynnik trzydzieści dwa na przykład.

    @Dostęp do adresów parzystych/nieparzystych…
    Akurat data alignment to jest temat rzeka. Zawsze ma znaczenie dla wydajności, nawet na pececie. A niektóre architektury po prostu kładą się z BUS ERROR jeśli wystawić adres niewłaściwy dla typu operacji.

    • cmos pisze:

      @rodzaje pamięci

      Mi chodzi o to, że niemal wszystkie języki programowania tak z półki bazują na architekturze Harvard i tyle, a niektóre nawet na von Neumannie. Nawet zmienne zadeklarowane jako const w pececie lądują w RAMie, ich niezmienność wymusza tylko kompilator. Dalej: typowy programista pecetowy nawet nie zdaje sobie sprawy że zmienne inicjalizowane zajmują pamięć podwójnie – raz sama zmienna, a drugi raz wartość inicjalna – to wszystko są dla niego nieistotne szczegóły, on operuje tylko na abstrakcji sprzętu, a pamięci jest zawsze dość.

      Oczywiście programowanie bliskie sprzętowi to zupełnie co innego, ale to nie jest działka „zwykłego programisty pecetowego”.

  2. dobiasz pisze:

    Jako świeżo upieczony i jeszcze zielony (2 mce) pracownik automotive, strzygę uszami na kolejne notki 🙂

Skomentuj i Ty

Komentowanie tylko dla zarejestrowanych i zalogowanych użytkowników. Podziękowania proszę kierować do spamerów