Wyślij zapytanie Dołącz do Sii

Pracując nad oprogramowaniem dla branży automotive, w pewnym momencie stykamy się z koniecznością dostępu do wewnętrznych zmiennych ECU (ang. Electronic Control Unit). Pierwszym naszym pomysłem może być oczywiście debugger (np.: Lauterbach TRACE32, iSYSTEM WinIdea), nierzadko jednak zdarzają się sytuacje, gdy jest on niewystarczający.

Dzieje się tak:

  • gdy dysponujemy jedynie plikami wykonywalnymi (skompilowanym kodem źródłowym aplikacji), np.: .exe, .dll, .bin, .hex, .elf bez symboli),
  • gdy fizycznie nie jesteśmy w stanie podpiąć debuggera (np.: podczas testów w samochodzie),
  • podczas prac nad prototypowaniem urządzenia (ang. Rapid Control Prototyping)
  • podczas kalibracji i pomiarów różnorodnych parametrów ECU (np.: za pomocą symulacji rzeczywistego urządzenia w programie Vector CANoe) w systemach HIL (Hardware-in-the-loop) /SIL (Software-in-the-loop),
  • w analizie problemów występujących sporadycznie.

We wspomnianych powyżej sytuacjach z pomocą może nam przyjść protokół XCP (ang. Universal Measurement and Calibration Protocol), który z powodzeniem jest stosowany w świecie automotive, a nawet szerzej – po prostu w systemach wbudowanych.

W poniższym artykule chciałbym przedstawić podstawowe założenia teoretyczne tego protokołu oraz dostępne funkcjonalności w praktyce.

Wprowadzenie do protokołu XCP

Protokół XCP został ustandaryzowany w 2003 roku przez ASAM (ang. Association for Standardization of Automation and Measuring Systems). Założeniami nowego protokołu zostały przede wszystkim:

  • bazowanie na architekturze typu Master – Slave,
  • niezależność od rodzaju fizycznej magistrali.

Podstawowym zaś celem nowego standardu stało się umożliwienie dostosowania (odczyt i/lub zapis) parametrów wewnętrznych ECU – pomiar i kalibracja, w taki sposób, aby z jednej strony zmniejszyć restrykcyjne wymagania dotyczące korzystania z zasobów ECU, z drugiej jednak zapewnić maksymalną prędkość transmisji.

W praktyce opracowano standard podstawowy opisujący założenia i komunikację samego protokołu oraz kilka dodatkowych, skupionych na warstwach transportowych konkretnych magistrali – CAN, FlexRay, Ethernet (UDP/IP oraz TCP/IP), USB, SPI, SCI.

XCP – model warstwowy
Ryc. 1 XCP – model warstwowy

Zdefiniowano również, że dostęp do parametrów i zmiennych wewnątrz ECU zostanie zapewniony za pomocą informacji o ich adresach w pamięci, zaś wszystkie informacje niezbędne do uzyskania do nich dostępu oraz pozostała konfiguracja będą zawarte w znormalizowanych plikach w standardzie ASAM MCD-2 MC, czyli plikach z rozszerzeniem .a2l. Szerzej o tych plikach opowiem w ostatniej części tego artykułu.

Najnowszą dostępną wersją protokołu XCP jest wersja 1.5 wprowadzona w roku 2017.

Protokół XCP – model komunikacji

W tym artykule nie mam zamiaru przedstawiać całościowo protokołu XCP, gdyż są do tego stosowne dokumentacje. Chciałbym jednak pokrótce opisać podstawy XCP, abyście łatwiej zrozumieli dalsze zagadnienia.

Komunikacja XCP opiera się, tak jak wspomniałem powyżej, na wymianie pakietów (ang. XCP Packets) pomiędzy układami Master – Slave. Wyróżniamy dwie grupy pakietów:

  • CTO (ang. Command Transfer Object) do transmisji podstawowych komend (ang. CoMmanD), odpowiedzi na te komendy (ang. RESponse), zgłaszania błędów podczas wykonywania komend (ang. ERRor), obsługi sytuacji specjalnych (ang. EVent) oraz obsługi pakietów serwisowych (ang. SERVice Request Processor).
  • DTO (ang. Data Transfer Object) do transmisji danych DAQ (ang. Data AcQuisition) i STIM (ang. Data STIMulation), o których będzie jeszcze mowa.

Ramka XCP

Ramka XCP składa się z 3 części:

  • nagłówka (XCP Header),
  • głównej części pakietu (XCP Packet),
  • zakończenia (XCP Tail).

Warto zauważyć, że pakiet XCP sam w sobie jest niezależny od warstwy transportowej, co oznacza de facto, że każdorazowo zostaje on obudowany informacjami specyficznymi dla danej magistrali (CAN/FlexRay/etc.). Poniższy rysunek prezentuje to w nieco bardziej przystępny sposób:

Ramka XCP
Ryc. 2 Ramka XCP

W celu zrozumienia, jakie informacje są przekazywane w poszczególnych polach pakietu, poniżej zamieszczam ich opis:

  • Identyfikator pakietu (PID) – pozwala na identyfikację przesyłanej wiadomości.
  • Wyrównanie (FILL) – pole opcjonalne, które można wykorzystać do wypełnienia, jeśli nie ma wystarczającej ilości danych do przesłania.
  • Absolutna liczba list DAQ (DAQ).
  • Znacznik czasu (Timestamp) jest to pole opcjonalne wykorzystywane do przesyłania informacji o czasie systemowym. Może być użyty przez komendę GET_DAQ_CLOCK lub jako informacja dodatkowa przy korzystaniu z DAQ/STIM.
  • Pole danych przy transmisji pakietów CTO (zawiera specyficzne parametry) lub DTO (zawiera dane DAQ/STIM).

XCP funkcjonalności

XCP oferuje szereg przydatnych funkcjonalności. Część z nich jest konieczna do implementacji, natomiast inne są jedynie opcjonalne, w zależności od potrzeb czy wymagań funkcjonalnych projektu. W tym miejscu chciałbym omówić najważniejsze z nich.

Nawiązanie połączenia

Ryc. 3 XCP – nawiązanie połączenia
Ryc. 3 XCP – nawiązanie połączenia

Nawiązanie połączenia z XCP Slave polega na wysłaniu komendy CONNECT (kod 0xFF). W polu MODE wybrałem tryb Normalny (zdefiniowanym przez standard), choć istnieje możliwość zdefiniowania własnej implementacji nawiązywania połączenia.

Informacje zwrotne mówią nam, że:

  • będziemy mieli do dyspozycji DAQ i STIM (pole RESOURCE),
  • do transmisji danych został wybrany format Intel, rozmiar elementu pod jednym adresem to 1 Bajt, Slave Block Mode jest dostępny, komenda GET_COMM_MOD_INFO zapewnia dodatkowe informacje (pole COMM_MODE_BASIC),
  • maksymalny rozmiar pakietu CTO to 0x96 (pole MAX_CTO),
  • maksymalny rozmiar pakietu DTO to 0x2C (pole MAX_DTO),
  • wersja protokołu XCP to 1.0 (pole XCP Protocol Layer Version Number),
  • wersja warstwy transportowej XCP to 1.0 (pole XCP Transport Layer Version Number).

Zakończenie połączenia

Aby zakończyć połączenie, należy wysłać komendę DISCONNECT:

XCP – zakończenie połączenia
Ryc. 4 XCP – zakończenie połączenia

Pomiar metodą odpytywania (ang. Polling Measurement)

Jest to podstawowa funkcjonalność pozwalająca na odczytywaniu wartości zmiennej za pomocą pojedynczego żądania, używając komendy SHORT_UPLOAD lub sekwencji komend SET_MTA i UPLOAD.

XCP – metoda odpytywania
Ryc. 5 XCP – metoda odpytywania

W powyższej animacji widzimy wysłanie komendy SHORT_UPLOAD (0xF4) do odczytania wartości zmiennej zlokalizowanej pod adresem 0x12345678 o rozmiarze 2 Bajtów. W odpowiedzi uzyskujemy informację, że zmienna ma wartość 0x0C07.

Pomiar cykliczny

Ten rodzaj pomiaru umożliwia odczyt (DAQ) i/lub zapis (STIM) wartości zmiennych w sposób cykliczny. W porównaniu do poprzedniego mechanizmu konfiguracja jest trochę bardziej skomplikowana i wymaga zrozumienia kilku technicznych kwestii.

Po pierwsze potrzebujemy informacji o adresach zmiennych oraz ich rozmiarach (wyrażonych w Bajtach). Korzystając z DAQ/STIM, będziemy chcieli często odczytywać lub zmieniać wartości większej ilości zmiennych, więc de facto będziemy tworzyć tablicę takich par (adres + rozmiar w Bajtach) (ang. Object Descriptor Table (ODT)).

Po drugie, utworzone w powyższy sposób tablice możemy następnie grupować w listy DAQ/STIM. Listy te można tworzyć na 3 sposoby:

  1. Predefiniować w ECU (listy DAQ/STIM oraz tablice ODT są predefiniowane; ze względu na brak elastyczności ta metoda rzadko jest używana).
  2. Definiować statycznie (listy DAQ/STIM oraz tablice ODT są predefiniowane, ale zmienne można edytować).
  3. Definiować dynamicznie, by mieć pełną kontrolę na listami, tablicami ODT oraz samymi zmiennymi w czasie rzeczywistym.

Ostatnią częścią konfiguracji są zdarzenia (Eventy). Są one niczym innym jak cyklicznymi funkcjami, w których można uruchamiać DAQ /STIM. Na etapie tworzenia zdarzeń definiuje się ich cykliczność, priorytet, przypisanie funkcji DAQ, STIM lub DAQ/STIM. Warto też zaznaczyć, że Eventy mogą być powiązane z większą ilością list.

Poniższy rysunek przedstawia przykład zależności pomiędzy definicjami opisanymi wyżej. Utworzyłem zdarzenie XCP_TestEvent z jedną listą typu DAQ, która zawiera jedną tablicę ODT z trzema zmiennymi.

XCP – zależności pomiędzy zdarzeniem, DAQ listą i tablicą ODT
Ryc. 6 XCP – zależności pomiędzy zdarzeniem, DAQ listą i tablicą ODT

DAQ+STIM (ang. bypassing)

Gdy omawiałem parametry określające XCP Event, wspomniałem, że może on być nie tylko typu DAQ lub STIM, ale również typu DAQ/STIM. W takiej sytuacji mówimy o tzw. bajpasie – pobieramy dane z ECU, przetwarzamy je poza ECU i następnie zapisujemy z powrotem do ECU. W tym mechanizmie ważne jest oczywiście zapewnienie pełnej integralności danych oraz spełnienie warunków synchronizacji odczytu i zapisu do pamięci.

Z punktu widzenia konfiguracji będziemy potrzebować dwie listy:

  • jedną typu DAQ,
  • jedną typu STIM.

Programowanie pamięci (ang. Flash programming)

Programowanie za pomocą protokołu XCP oznacza możliwość zapisu danych pod wskazany obszar w pamięci nieulotnej Flash. Proces zapisu lub czyszczenie pamięci wygląda następująco:

  • Przygotowanie istotnych parametrów z punktu widzenia zarządzania pamięcią (np.: kontrolowanie wersji danych, które chcemy nadpisać, sprawdzenie, czy ECU zezwala na zapis pod konkretnymi adresami, etc.).
  • Wykonanie operacji przesyłania danych do ECU.
  • Sprawdzenie, czy zapis lub czyszczenie pamięci powiodły się (np.: sprawdzenie sumy kontrolnej).

Warto więc zauważyć, że standard XCP definiuje jedynie szkielet mechanizmu oraz podstawowy zestaw komend realizujących zapis lub czyszczenie pamięci, natomiast sposób w jaki ostatecznie zostanie on zaimplementowany, zależy od wymagań danego projektu.

Ze względu na ograniczone możliwości bezpieczeństwa operacji programowania pamięci za pomocą protokołu XCP mechanizm ten powinien być używany jedynie w fazie prac rozwojowych oprogramowania, a nie w produkcie końcowym.

Mechanizm ochronny XCP

Podczas prac nad standardem XCP pomyślano również o zabezpieczeniu dostępu do funkcjonalności XCP w sposób nieautoryzowany. Do tego celu wykorzystano mechanizm seed-and-key.

Podczas próby połączenia XCP Master otrzymuje od XCP Slave wygenerowaną przez niego liczbę pseudolosową (ang. seed). Następnie Master przy pomocy algorytmu generuje klucz (ang. key), po czym wysyła go do XCP Slave. Slave również przy pomocy tego samego algorytmu generuje własny klucz i porównuje go z tym otrzymanym od Mastera. Jeżeli klucze są identyczne, XCP Slave pozwala na rozpoczęcie komunikacji. Graficzne ujęcie tego procesu przedstawiono na animacji poniżej.

XCP – mechanizm seed-and-key
Ryc. 7 XCP – mechanizm seed-and-key

Chciałbym również wspomnieć o względach bezpieczeństwa związanych z obecnością sterownika XCP w kodzie produkcyjnym. Jest to zagadnienie ściśle związane z danym projektem i wymaganiami klienta. Spotyka się różne podejścia do niego – od najbardziej rygorystycznego, w którym XCP w ogóle nie jest brane pod uwagę w procesie kompilacji wydań produkcyjnych, po bardziej liberalne, gdzie XCP, co prawda jest dezaktywowane, ale z pozostawioną „furtką” do ponownej aktywacji za pomocą unikalnych sekwencji diagnostycznych.

Tak więc nie mamy w tym temacie jednego rozwiązania, lecz każdy przypadek wymaga indywidualnej analizy.

Zarządzanie pamięcią podczas komunikacji z XCP

Ważnym zagadnieniem jest prawidłowe zarządzanie pamięcią podczas komunikacji z XCP.

Podczas normalnej pracy ECU operuje na pamięci Flash. Mamy zatem ograniczoną możliwość modyfikacji pojedynczych obiektów w niej zapisanych. Jest to podyktowane jej określoną żywotnością (maksymalna ilość operacji zapisu/kasowania). Co więc w sytuacji, gdy w kodzie produkcyjnym konieczne jest częste wykonywanie kalibracji ECU, np.: w systemie czujników LiDAR? W jaki sposób dokonywać takich cyklicznych zapisów w czasie rzeczywistym (ang. at runtime)?

Z pomocą najczęściej przychodzi nam wykorzystanie pamięci RAM, która co prawda wymaga zasilania, by móc przechowywać informacje, ale za to oferuje łatwy odczyt i zapis. Nie występuje tu również problem z jej żywotnością.

Będzie więc chodziło o przechowywanie parametrów w pamięci RAM podczas ich modyfikacji. Można zatem użyć części RAM-u jako bufora dla danych odczytanych z Flash. Owo odczytanie zawartości i skopiowanie jej do pamięci RAM zazwyczaj dokonywane jest podczas startu aplikacji, zaś podczas wyłączania następuje całościowy lub częściowy (zmiany mogą być wykrywane za pomocą sum kontrolnych) „powrotny” zapis do pamięci Flash.

Pliki konfiguracyjne A2l

Ostatnim zagadnieniem, które chciałbym poruszyć, są pliki a2l. Tak jak wspomniałem, konfiguracja XCP i symboliczne przypisanie zmiennych do ich adresów w pamięci ECU odbywa się właśnie za pomocą plików a2l.

Oto kilka wycinków z plików a2l ukazujących szereg parametrów konfiguracyjnych niezbędnych do poprawnego działania konkretnych funkcjonalności:

  • Konfiguracja protokołu XCP:
       /begin PROTOCOL_LAYER
        0x0101 			           /* XCP protocol layer version */
        20				           /* T1 [ms] Time-out of the standard CTO */
        20000			           /* T2 [ms] Time-out of the checksum calculation */
        20000			           /* T3 [ms] Time-out of the non-volatile memory programming: eg.  PROGRAM_START */
        20000			           /* T4 [ms] Time-out of the non-volatile memory programming: PROGRAM_CLEAR */
        20000			           /* T5 [ms] Time-out of the non-volatile memory programming: PROGRAM */
        20000			           /* T6 [ms] Time-out of the command CONNECT(USER_DEFINED) */
        20000			           /* T7 [ms] Time-out of the pre-action */
        100 			           /* MAX_CTO: Indicates the maximum length of a CTO packet in bytes. */
        50 				           /* MAX_DTO: Indicates the maximum length of a DTO packet in bytes. */
        BYTE_ORDER_MSB_LAST	       /* Byte Order */
        ADDRESS_GRANULARITY_BYTE   /*The address granularity indicates the size of an element at a single address. */
        OPTIONAL_CMD GET_ID		   /* XCP-Code of optional command supported by the slave */
        OPTIONAL_CMD SHORT_UPLOAD
      /end PROTOCOL_LAYER
  • Konfiguracja Eventu DAQ XCP:
     /begin EVENT
        Xcp_TestEvent         /* EVENT_CHANNEL_NAME */
        Xcp_Test              /* EVENT_CHANNEL_SHORT_NAME */
        0                     /* EVENT_CHANNEL_NUMBER */
        DAQ 
        1                     /* MAX_DAQ_LIST */
        1                     /* TIME_CYCLE */
        1                     /* TIME_UNIT */ 
        0                     /* PRIORITY */
      /end EVENT
  • Konfiguracja DAQ XCP:
   DYNAMIC	                            /* The flag indicates whether the DAQ lists that are not PREDEFINED shall be     
	                                        configured statically or dynamically */
      5                                     /* MAX_DAQ: Total number of available DAQ lists */ 
      5                                     /* MAX_EVENT_CHANNEL: Total number of available event channels */
      0                                     /* MIN_DAQ: Total number of predefined DAQ lists*/
      OPTIMISATION_TYPE_DEFAULT             /* Type of Optimisation Method the master preferably should use. */
      ADDRESS_EXTENSION_FREE                /* ADDRESS_EXTENSION */
      IDENTIFICATION_FIELD_TYPE_ABSOLUTE    /* IDENTIFICATION_FIELD */
      GRANULARITY_ODT_ENTRY_SIZE_DAQ_BYTE   /* GRANULARITY_ODT_ENTRY_SIZE_DAQ */
      7                                     /* MAX_ODT_ENTRY_SIZE_DAQ */
  • Konfiguracja dostępu do odczytu i zapisu zmiennej XCP_TestVar typu unsigned word i znajdującej się pod adresem 0x12345678:
    /begin CHARACTERISTIC XCP_TestVar ""
      VALUE 0x12345678 __UWORD_Z 0 NO_COMPU_METHOD 0 65535
      SYMBOL_LINK " XCP_TestVar " 0
    /end CHARACTERISTIC

Podsumowanie

Moim celem w powyższym artykule było przyjrzenie się kluczowym zagadnieniom i zastosowaniom protokołu XCP. Przede wszystkim zależało mi na podkreśleniu jego uniwersalności i elastyczności. Cechy te bowiem uczyniły go jednym z ulubionych narzędzi inżynierów rozwijających zaawansowane systemy motoryzacyjne czy też inżynierów testów.

Mam nadzieję, że po przeczytaniu wpisu znajdą się osoby zainteresowane dalszym zgłębianiem tematów związanych z XCP i również takie, które będą chciały w praktyce wykorzystać szereg przydatnych funkcji oferowanych przez ten protokół.

Bibliografia

5/5 ( głosy: 24)
Ocena:
5/5 ( głosy: 24)
Autor
Avatar
Rafał Szuta

Inżynier oprogramowania z ponad 7-letnim doświadczeniem, w większości w projektach branży automotive dla takich marek jak VW, Porsche, Daimler. Specjalizujący się w platformie AUTOSAR w warstwie Basic Software. Po pracy gra w tenisa i squasha

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Może Cię również zainteresować

Pokaż więcej artykułów

Bądź na bieżąco

Zasubskrybuj naszego bloga i otrzymuj informacje o najnowszych wpisach.

Otrzymaj ofertę

Jeśli chcesz dowiedzieć się więcej na temat oferty Sii, skontaktuj się z nami.

Wyślij zapytanie Wyślij zapytanie

Natalia Competency Center Director

Get an offer

Dołącz do Sii

Znajdź idealną pracę – zapoznaj się z naszą ofertą rekrutacyjną i aplikuj.

Aplikuj Aplikuj

Paweł Process Owner

Join Sii

ZATWIERDŹ

This content is available only in one language version.
You will be redirected to home page.

Are you sure you want to leave this page?