Monitor sběrnice LIN - dekódování v C

HellMaster

Monitor sběrnice LIN - dekódování v C
« kdy: 11. 04. 2013, 16:33:49 »
Zdravim vsechny,

pomoci karty od National Instruments jsem schopen monitorovat data po sbernici LIN. NI ma API v C, kterym lze data z karty vycist a zapsat do struktury nasledujiciho typu:

Kód: [Vybrat]
typedef struct
{
timestamp;
ID;
data_length;
data[8]
} LIN_DATA

Vypsat tyto data neni problem, ale zde prichazi hacek. Frame zpravy daneho ID reprezentuje nejakou konkretni zpravu.
Napriklad:
zprava s ID 10 bude GetStatus, bude mit 32 bitu:
bit 0 - 5 vyska
bit 6 - 11 sirka
bit 12 - 17 delka
.
.
.

Informace o techto framech mam ulozene v externim souboru. Jakym zpusobem dekodovat detaily techto zprav? Napriklad z karty vyctu zpravu s ID 10. Vypisu ji a k tomu potrebuju vypsat/rozklicovat jednotlive podzpravy, protoze tato informace je pro uzivatele prinosnejsi, nez 8 byte v hexa. Problem je, ze soubor s definici ramcu zprav je projekt od projektu odlisny, cili nelze nadefinovat hlavickovy soubor, ten inkludovat a toto cele zkompilovat.

Pro lepsi predstavu pro monitorovani LIN/CAN sbernice slouzi napr. HW CANoe nebo CANalyzer od spolecnosti VECTOR. Bohuzel je velmi drahy a licencovany, proto jsem si chtel udelat vlastni, jednodussi variantu. :-)

Diky za jakekoli napady! :-)
« Poslední změna: 12. 04. 2013, 14:26:42 od Petr Krčmář »


gamer

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #1 kdy: 11. 04. 2013, 17:53:19 »

HellMaster

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #2 kdy: 11. 04. 2013, 20:11:02 »
Cau, diky za link. Prolitnul jsem to zbezne, ale zatim jsem z toho nevykoukal nic moudreho nebo pouzitelneho.

xcvcdvsd

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #3 kdy: 11. 04. 2013, 20:23:26 »
v externim souboru mas definice, ze napr. pro ID 4 mas bajty interpretovat treba jako 3 inty za sebou.
nebo pro ID 7, ze to jsou treba 2 floaty za sebou. apod.

i kdyz maji ruzne projekty ruzne definice v externim souboru,  furt tam bude definice neco jako:
ID1 vyska 2bajty = 2bajtove_cele_cislo, sirka 2bajty = 2bajtove_cele_cislo
ID2 teplota 4 bajty = 4_bajtovy_float.

pokud budes mit v kodu programu nadefinovany vsecky vystupni formaty 2_bajtove_cele_cislo, 3_bajtove_cele_cislo, 4_bajtovy_float, 10_bajtovy_string a v externim souboru budou jenom tyto, tak nemas problem.

HellMaster

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #4 kdy: 12. 04. 2013, 06:31:17 »
At jsme konkretni, tak v externim souboru mam nasledujici:

Frames {
   BCM_LIN5_A : 48, BCM_Gp, 4   {
      UserSetMinute, 0;
      UserSetSecond, 8;
      UserSetHour, 16;
      CarModeL5, 24;
   }
   BCM_LIN5_B : 32, BCM_Gp, 2   {
      MonitoringRestartReqBCML5, 9;
   }
   BCM_LIN5_C : 55, BCM_Gp, 8   {
      RHSBLSlewRateRequest, 0;
      RHFrontSMRequest, 4;
      LHFrontSMRequest, 6;
      RHSBLPWMDutyRequest, 8;
      RHDRLPosSlewRateRequest, 16;
      LHSBLSlewRateRequest, 20;
      RHDRLPosPWMDutyReq, 24;
      LHDRLPosSlewRateReq, 32;
      LHDRLPosPWMDutyReq, 40;
      LHSBLPWMDutyRequest, 48;
   }
   CLOCK_A : 49, CLOCK, 4   {
      CLKHWPartNo, 0;
      CLKFaultStatus, 16;
.
.
.
.
}

Nazev zpravy, jeho ID, pocet bytu a pak nasleduje vnitrni struktura, kde jsou nadefinovane offsety jednotlivych parametru v bitech. Jak je videt, tak kazda podzprava ma jine vnitrni usporadana. Nektere podzpravy jsou 8 bitu dlouhe, jindy 6 atp...
Cili ja za behu programu neznam tuto strukturu a nemuzu si ji teda nikde predem nadefinovat a zakomponovat ji do applikace. Toto musi nejak probehnout za behu programu.


sdrgtdasgf

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #5 kdy: 12. 04. 2013, 06:51:27 »
UserSetMinute, 0;
UserSetSecond, 8;
UserSetHour, 16;
CarModeL5, 24;

ale z tech offsetu vidim, ze UserSetMinute ma delku osm bitu viz. offsety 0-8, tak bych to reprezentoval jako cislo 0-255 v ulozene v charu.

RHSBLSlewRateRequest, 0;
RHFrontSMRequest, 4;
LHFrontSMRequest, 6;

RHSBLSlewRateRequest ma delku 4 bity takze zase jako cislo 0-127 ulozene v char.

takze jedina vec je predem si urcit jak ruzne delky v bitech budu reprezentovat jako typy.
napr.

4 bity = char
8 bitu = char
16 bitu = int nebo float, tady uz by bylo asi treba rozhodnout i podle nazvu promene.
nebo pokud vim, ze pracuju jen s inty.

HellMaster

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #6 kdy: 12. 04. 2013, 07:07:19 »
To vidis ted, ale co kdyz ti hodim jiny file kde toto bude nadefinovane jinak? :-)

A i nazvy parametru budou jine. Takze nejake preddefinovani nemuzu pouzit.

Krom toho ja potom budu potrebovat z tech 8 bytu vykrojit tu 6bitovou cast a vypsat ji. Coz by se dalo udelat najkym maskovanim a posunem bitu.

adfgsdfgsdfgdsg

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #7 kdy: 12. 04. 2013, 08:53:41 »
To vidis ted, ale co kdyz ti hodim jiny file kde toto bude nadefinovane jinak? :-)

A i nazvy parametru budou jine. Takze nejake preddefinovani nemuzu pouzit.

Krom toho ja potom budu potrebovat z tech 8 bytu vykrojit tu 6bitovou cast a vypsat ji. Coz by se dalo udelat najkym maskovanim a posunem bitu.

na nejakem standardu se ale musis zastavit.

UserSetMinute, 0;
UserSetSecond, 8;
UserSetHour, 16;
CarModeL5, 24;
napriklad CarModeL5 zacina na 24 bitu a konci na 48 bitu, takze to podle me bude stringovy identifikator, ale treba by to mohl
by i nejaky vicebajtovy integer. to z konfiguraku nevyctes, to si holt musis preddefinovat predem.

kdyz mam nekde 4bity tak to muze byt cislo, nebo znak, dokonce i nejaky float s pevnou desetinou teckou.
Kdyz nekde v nazvu vidim minute, second, hour tak predpokladam integer cislo.

HellMaster

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #8 kdy: 12. 04. 2013, 10:21:40 »
CarModeL5 zacina na bitu 24 a je az do konde, coz je v tomto pripade bit 32. To neni ale podstatne. Ve vysledku to jsou vsechno jen cisla. Neni to string a podle me ani float. Vsechno to jsou cisla typu int.

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #9 kdy: 12. 04. 2013, 10:30:56 »
Asi mně nějak nedochází, co řešíš. Máš jakýsi definiční soubor v jakémsi formátu a máš data, která jsou formátovaná podle té definice.

No tak si musíš napsat parser toho definičního souboru, zparsovat ho, uložit výsledek do nějaké rozumné struktury v paměti a potom data dekódovat na základě té struktury. V čem je teda problém? Nechceš to přeformulovat na trochu jinou otázku než "jak to udělám"?

adfgsdfgsdfgdsg

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #10 kdy: 12. 04. 2013, 11:08:25 »
CarModeL5 zacina na bitu 24 a je az do konde, coz je v tomto pripade bit 32. To neni ale podstatne. Ve vysledku to jsou vsechno jen cisla. Neni to string a podle me ani float. Vsechno to jsou cisla typu int.

tak kdyz jsou to vsecko inty s ruznou bitovou velikosti, tak nemas problem. na vtupu mas char[ruzna_delka]
a ty pak jenom nasypes tolik bitu kolik chces pomoci bitovych operaci treba do vystupniho long longu.
klidne muzes pouzivat typ long long dlouhy 64 bitu, a do toho vleze vsecko :-)

HellMaster

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #11 kdy: 12. 04. 2013, 11:18:50 »
Asi mně nějak nedochází, co řešíš. Máš jakýsi definiční soubor v jakémsi formátu a máš data, která jsou formátovaná podle té definice.

No tak si musíš napsat parser toho definičního souboru, zparsovat ho, uložit výsledek do nějaké rozumné struktury v paměti a potom data dekódovat na základě té struktury. V čem je teda problém? Nechceš to přeformulovat na trochu jinou otázku než "jak to udělám"?

Diky za poznamku, asi jsem to vysvetlil spatne. Jelikoz neocekavam nejake kusy kodu apod. jen rady, jakym zpusobem toto implementovat, tak jsem to psal obecneji. Takze:

Po sbernici prijimam a vysilam data, kde ramec vypada zjendodusene nasledovne:

ID (1byte), Data (2 - 4 - 8 bytes delka se lisi)

Karta od National Instrument umi pres jejich C API vycist tyto data do struktury, ktera vypada nasledovne:

Kód: [Vybrat]
typedef struct
{
     ID;
     timestamp;
     data_length;
     UINT8 data[8];
} NITYPE_LIN_STRUCT

Priklad: ID = 48; timestamp = 5000; data_length = 4; data = 0A 25 3C 10 (hex) => data[8] = {10, 37, 60, 10, 0, 0, 0, 0}

Mam externi soubor ldf (LIN description file) ktery mi popisuje vnitrni strukturu prijatych dat podle ID zpravy (tento soubor je nezavisly na NI karte a je dodavan od treti strany):

Kus vypisu z toho souboru vypada nasledovne:

Kód: [Vybrat]
Frames {
BCM_LIN5_A : 48, BCM_Gp, 4 { (nazev zpravy, ID zpravy, nepodstatne, delka zpravy v bytech)
UserSetMinute, 0;       (sub-informace, bit offset - tento parametr zacina na bitu 0)
UserSetSecond, 8;      (sub-informace, bit offset - tento parametr zacina na bitu 8)
UserSetHour, 16;
CarModeL5, 24;
}
BCM_LIN5_C : 55, BCM_Gp, 8 {
RHSBLSlewRateRequest, 0;
RHFrontSMRequest, 4;
LHFrontSMRequest, 6;
RHSBLPWMDutyRequest, 8;
RHDRLPosSlewRateRequest, 16;
LHSBLSlewRateRequest, 20;
RHDRLPosPWMDutyReq, 24;
LHDRLPosSlewRateReq, 32;
LHDRLPosPWMDutyReq, 40;
LHSBLPWMDutyRequest, 48;
}
CLOCK_A : 49, CLOCK, 4 {
CLKHWPartNo, 0;
CLKFaultStatus, 16;
.
.
.
} // End of Frame description

Takze pro nas prikald,
UserSetMinute = 16 (0x10)
UserSetSecond = 60 (0x3C)
UserSetHour = 37 (0x25)
CarModeL5 = 10 (0x0A)

Problem je, ze ten definicni soubor se meni projekt od projektu. Takze priste muze byt na ID 48 zprava GetParam, delka 2 byte a muze v sobe mit zakodovanych 8 informaci, kazda po dvou bitech.

Otazka zni, jaky zpusob zvolit pro predzpracovani teto informace pro nasledny vypis na obrazovku?

priklad:
Kód: [Vybrat]



NITYPE_LIN_STRUCT data[256]; // mam nactenych 256 zprav

ReadData(&data);

for(i = 0; i < pocet_zprav; i++)
{
     printf("ID: %d,  Time: %d,   Data Length: %d, Byte1: %d, Byte2: %d, Byte3: %d Byte4: %d, Byte5: %d....\n", data[i].ID, data[i].timestamp, ....)
     for(j = 0; j < pocet_sub_informaci; j++)
           printf("%sz: %d\n", [b]data[/b], [b]hodnota[/b]);
}

Jakym zpusobem udelat predzpracovani dat z externiho souboru (jak je manageovat), abych k nim potom pri vypisu mohl pristoupit a pomoci nich dekodoval onech 2-4-8 prijatych bytu?

Cili, otevru soubor -> predzpracovani dat a ulozeni nekam -> mozno spustit monitorovani sbernice (data uz jsou predpripravena a vim, podle jakeho klice dekodovat)



Logik

  • *****
  • 1 031
    • Zobrazit profil
    • E-mail
Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #12 kdy: 12. 04. 2013, 12:02:50 »
No tak si z toho popisu zprávy udělej deskriptor zprávy přesně v tom stylu: seznam
polozek ve tvaru

char[] nazev
int start
int length

ukladej si presne co ti vraci ta knihovna a pomoci tohodle deskriptoru tahej data primo z toho uintu, ne


Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #13 kdy: 12. 04. 2013, 12:10:39 »
To jenom podrobneji popisujes porad to stejny. Kde mas presne problem? Na co presne se ptas? Jak parsovat ten definicni soubor, v jakem meziformatu si ho ulozit? Nebo jak ten meziformat pouzit na dekodovani dat?


slonik

Re:Monitor sbernice LIN - dekodovani zprav v C
« Odpověď #14 kdy: 12. 04. 2013, 12:11:50 »
to BCM_Gp neviem co je.
Kód: [Vybrat]
struct subor {
  struct idcko *pole_id;
  size_t pole_id_len;
}

struct idcko {
 char * popisok;
 size_t pocet_chlievikov;
 struct chlievik *pole_ch;
}

struct chlievik {
char * popisok;
off_t offset;
size_t typ;
}

teraz to tychto struktur naloadujes ten subor.

a nasledne vypisujes
Kód: [Vybrat]
NITYPE_LIN_STRUCT sprava;

struct subor *s;
struct idcko *muid = s->pole_id[sprava.ID];

fprintf(stdout, "Id spravy je %u %s \n", sprava.ID, muid->popisok);

int i;
for (i = 0; i < muid->pocet_chlievikov; i++){
 struct chlievik * chliev = &muid->pole_ch[i];
 char * num = &sprava.data[chliev->offset];

   fprintf(stdout, "V chlieviku %u %s je cislo %s \n", i, chliev->popisok, muid->popisok, num);


}