Hallo,
ich sitzte grad seit etlichen Stunden um ein ganz komisches CAN-Problem
zu beseitigen.
Ich nutze einen Testaufbau mit dem Atmel dvk90can, das einen at90can128
enthält.
Mein Can-Netz besteht aus eben diesem Evaluationsboard angeschlossen an
einen Fahrzeug-CAN (ja das ist so richtig, gewollt und erlaubt).
Mein eigentliches Problem besteht beim Empfangen von Can-Telegrammen.
Meine Routinen funktionieren alle hervorragend, bis zu einem bestimmten
Zeitpunkt, an dem eine bestimmte Menge an Nachrichten eingegaben ist.
In meiner ISR stecke ich die Nachricht in einen FiFo und re-aktiviere
anschließend das ensprechende Mob um erneut Daten empfangen zu können.
Curioser weise wird nach einer Weile das Mob nicht wieder aktiviert. Das
passiert reproduzierbar, aber nach unterschiedlich vielen Nachrichten
(meist so nach 1000 bis 100000 Nachrichten).
Ich habe 5 Mob mit je einer ID als für den Empfang konfiguriert. (Filter
sind jeweils so gesetzt, dass wirklich nur diese 5 Ids empfangen werden)
Fällt euch vielleicht was ein, wo ich noch suchen könnte? Der Fakt, das
die Kommunikation am Anfang geht, zeigt mit, dass meien Funktionen
richtig sind. Im übrigen wird auch parallel noch gesendet, dies wird nie
beeinträchtig - der chip stürzt also nicht ab.
Was könnte dazu führen, dass das Mob nicht mehr aktiviert wird?
vielen dank schonmal..
Mit viel Pech ist das ein Nebeneffekt eines anderen Problems z.B. einem
Stack Overflow, der dann irgendeine Variable zerschießt, die in der
Funktion zur Reaktivierung des MOBs benutzt wird.
Allerdings wird Dir kaum jemand helfen können, ohne den Code vor sich zu
haben. Evtl. ist irgendwo auch ein Denkfehler drin. Wir haben hier zwei
Baugruppen auf Basis der AVR CAN Controller und die haben noch nie
Probleme gemacht. Deshalb glaube ich nicht an einen Hardwarefehler.
Daniel wrote:
> Curioser weise wird nach einer Weile das Mob nicht wieder aktiviert. Das> passiert reproduzierbar, aber nach unterschiedlich vielen Nachrichten> (meist so nach 1000 bis 100000 Nachrichten).
Das könnte ein Atomic-Problem sein.
Du hast den Interrupt und eine Main-Funktion, die beide auf die
CAN-Register zugreifen. Dann müssen Read-Modify-Write und 16Bit-Zugriffe
atomar gemacht werden. Und auch die Zugriffe auf die FIFO.
Ich denke mal, das Enable-Bit ist auch lesbar. Dann lies einfach mal
nach dem Setzen zurück, ob es gesetzt ist und wenn nicht, setze es
nochmal.
Wenn das dann funktioniert, mußt Du ergründen, warum das erste Setzen
manchmal nicht geklappt hat.
Atomic-Probleme werden oftmals nicht verstanden und werden definitv
nicht durch das Betriebssystem abgefangen.
In größeren Systemen werden dann festgefressene Tasks durch Timeouts
wieder reaktiviert, anstatt die Ursache zu suchen.
Peter
hallo,
schon mal danke für die tips..doch leider lösen sie das problem noch
nicht:
ich überprüfe jetzt in der ISR nach dem ich das mob rekonfiguriert habe,
ob das Bit wirklich gesetzt ist. Das ist es immer. Trotzdem bricht der
Empfang irgendwann ab.
Außerdem habe ich die FIFO Funktionen atomar gemacht (also SREG
gepuffert, dann cli, dann SREG zurück)
Beides brachte es jedoch noch nicht.
Auch eine Deaktivierung des ID-Filters brachte keine abhilfe. Ich hatte
ein Mob so konfiguriert, dass es alle Nachrichten empfängt. Auch dieses
Mob wird nach einiger Zeit mysteriöser Weise "abgeschaltet".
Des Weiteren habe ich ein zweites, identisches Board ausprobiert: kein
Unterschied. Daher kann ich eigentlich einen Hardwarefehler
ausschließen.
Außer es ist ein Bug im Chip selbst.
Wenn ich, nach dem so ein Mob nicht mehr funktioniert, per Knopfdruck
ein weiteres registriere, läuft der Empfang wieder weiter, bis auch
dieses irgendwann nicht mehr tut. Selbst wenn ich ganz viele Mobs für
den Empfang auf allen Ids konfigurier, kommt der Empfang irgendwann zum
erligen. Es dauert halt nur länger (wobei dies länger dauert, als wenn
ich die gleiche Anzahl Mobs einzeln "verheize")
Mir kam grad der Begriff "zugespamt" in den Sinn... kann es sein, dass
da irgendein Stack überläuft oder so?...Wobei der Controller an sich ja
normal weiterläuft.
Wo könnte ich noch suchen? Was könnte ich noch überprüfen um den Fehler
weiter einzugrenzen? Ich hätte auch ein JTAG zur Verfügung.
CODE:
1
//can.c
2
3
ISR(CANIT_vect){
4
//captures all events, including reception and transmission complete
5
6
//determine what has happened
7
//first step: determine which m0b has caused an interrupt
8
uint8_tmObNumber=0;
9
10
mObNumber=CANHPMOB>>4;
11
12
CANPAGE=(mObNumber<<4);//select message object which caused the interrupt
13
14
//second step: determine what event has occurred (rx or tx);
15
if(CANSTMOB&(1<<RXOK)){//reception OK interrupt
16
//if there was a message received
17
//clear receive interrupt flag
18
CANSTMOB&=~(1<<RXOK);
19
setLedsToggled(1<<LED7);
20
21
MessageObjectmessage;
22
uint8_ti;
23
24
for(i=0;i<8;i++){//get the data
25
message.messageData[i]=CANMSG;
26
}
27
28
message.messageID=0;//get the id
29
message.messageID|=((uint16_t)CANIDT1<<8);
30
message.messageID|=((uint32_t)CANIDT2);
31
message.messageID>>=5;
32
33
34
//put that message into the buffer; if buffer is full; message will be lost
35
if(putMessageInBuffer(message,&canBufferRec)){
36
setLedsOn(1<<LED6);//geht nie an, es gibt nie einen buffer-overflow
37
}
38
39
CANCDMOB=(1<<CONMOB1);//reconfigure mailbox for reception, standard ids
40
41
while(!(CANCDMOB&(1<<CONMOB1))){
42
setLedsToggled(LED5);//geht auch nie an, d.h conmob1 wird immer gesetzt
43
CANCDMOB=(1<<CONMOB1);
44
}
45
46
}
47
elseif(CANSTMOB&(1<<TXOK)){//transmission ok interrupt
uint8_tread;// point to the index with oldest data
108
uint8_twrite;// points to empty index
109
}CanBuffer;
110
111
112
//in der Main.c
113
114
intmain(void){
115
while(1){
116
117
if(!getAMessage(&m)){//if there is an new Message available
118
119
canDatadata;
120
//data.e = m.messageData;
121
uint8_ti=0;
122
for(i=0;i<8;i++){
123
data.e[i]=m.messageData[i];
124
}
125
126
//in dem switch wird dann auch noch ein bisschen gerechnet;
127
//die leds flackern eine Weile, bis eben das Mob nicht mehr arbeitet.
128
129
switch(m.messageID){
130
case0x792:{//ACC_T01
131
setLedsToggled(1<<LED0);
132
break;}
133
case0x793:{//ACC_T02
134
setLedsToggled(1<<LED1);
135
break;}
136
case0x6B5:{//RADAR_INFO1
137
setLedsToggled(1<<LED2);
138
break;}
139
case0x130:{//CLU_1
140
141
setLedsToggled(1<<LED3);
142
break;}
143
144
case0x131:{//CLU_2
145
setLedsToggled(1<<LED4);
146
break;}
147
default:
148
break;
149
}
150
}
151
152
}
153
}
Falls ihr noch in die Init-Funktion oder Mob-Registrierung gucken wollt,
kann ich die natürlich auch noch posten.
Ich weiß, dass das ein ziemlich langer Beitrag ist und bedanke mich
schonmal fürs lesen.
Ich hoffe auch neuen Input,
Daniel
also ich hab noch was rausgefunden:
wenn ich mir das Can Enable Mob Register (CANEN1/2) anschaue, sehe ich,
dass wenn der Empfang zusammenbricht, auch das Mob nicht mehr verwendet
wird.
Es scheint also darauf hinaus zu laufen, dass ich irgendwo einen
Interrupt verpasse, in dem ich das Mob wieder aktiviere müsste.
Ist es denn möglich, dass Interrupts auflaufen und nicht abgearbeitet
werde?
Eigentlich ist es doch so, dass wenn ein Interrupt auftritt, wärend ein
anderer gerade verarbeitet wird, wird dieser trotzem im Anschluss auch
abgearbeitet. Sollten mehr als einer auftreten, wir nur einer ausgeführt
und ich verpasse ein paar Can-Nachrichten (was mir aber egal ist)..
Jedenfalls, wenn ich nebenbei nichts mehr sende (normaler Weise sende
ich alle 20ms drei Nachriten) scheint es zu keinem Fehler zu kommen (das
Ganze lief so, wie es sollte ein paar Minuten lang).
Das nützt mir allerdings nichts, da ich die empfangenen Daten ja
verarbeiten und wieder raus schicken muss.
habt ihr noch ne Idee?
ohne den ganzen Code gelesen zu haben:
Du achtest darauf dass die Register für fehlerhafte Sendungen nicht
überlaufen?
Du achtest darauf, nicht nur die Register neu zu initialisieren, sondern
auch die Datenregister auf 0 zu setzen?
Der at90Can128 ist mit bis zu 16 Mhz zu takten, wenn ich nicht irre.
Reicht die Zeit um Empfang und Sendung abzuarbeiten? Nicht alles, was an
Übertragungsraten machbar ist funktioniert dann auch.
Die Tatsache dass Du die Interrupts abschaltest heisst nicht, dass nicht
synchron Daten ankommen, es heisst nur dass sie keinen Interrupt mehr
auslösen. Ankommen und die Box belegen tun sie trotzdem.
Die Methode den Interrupt abzuwarten, dann im Reg den letzten Eintrag zu
suchen und abzuholen ist bei CAN etwas unpraktisch, weil in der gleichen
Zeit neue Nachrichten eingegangen sein können. Besser ist es die alle
Nachrichtenregister bei Interrupt auf neue Daten abzufragen.
Hab deinen Code nur kurz überflogen, aber mal so als Fragestellung, was
machst du, wenn zwei Message-Objekte gleichzeitig eintreffen? Gibt es
für jeden ein RX-Flag? Ich denke fast nicht, kenne allerdings diesen
Baustein nicht so. Vielleicht solltest du dir auch überlegen, evtl. auf
Polling beim Empfang umzusteigen, wenn dir, wie du oben sagst, es egal
ist, wenn du mal eine Nachricht nicht mitbekommst.
ich hab als Work-Around jetzt erstmal die TX-Interrupts abgestellt, die
ich eh nur genutz hatte um das tx-ok flag zurück zusetzten, es geht auch
ohne;
so läuft es vorerst stabil;
danke für eure Hilfe
Hallo Daniel,
ich habe das gleiche Problem wie du: nach einer gewissen Zeit scheint
der CAN-Controller einfach nichts mehr empfangen zu wollen.
Ein Ausstellen des TX-Interrupts hat bei mir allerdings auch nicht
geholfen.
Hast du inzwischen eine Erklärung für das Problem gefunden?
Viele Grüße,
Holger
Hallo
Ich hatte vor einiger Zeit auch ein ähnliches Problem. Der AT90Can hat
nach einer gewissen Zeit einfach keine Nachrichten mehr empfangen.
Ich hab mir das so erklärt:
Die Telegramme werden in der Reihenfolge, in der sie aktiviert werden,
den MObs zugeordnet. Dadurch wird auch die Priorität festgelegt, mit der
sie abgearbeitet werden. Mobs mit den niedrigsten Nummern haben die
höchste Priorität. Wenn ein zu empfangenes Telegramm direkt nach einem
aktiviert wird, das zu senden ist, dann gibt es bei dem zu empfangenem
Telegramm Probleme. Das Senden ist noch nicht abgeschlossen, wenn der
Empfang aktiviert wird. Nach Abschluss des Sendens gibt es ein leeres
MOb vor dem empfangenden MOb. Ist ein leeres MOb vor einem Telegramm,
das empfangen werden soll, dann wird das Telegramm vom Controller
empfangen und quittiert, aber nicht dem richtigem MOb zugeordnet. Somit
können die empfangenen Daten nicht ausgewertet werden.
Um das Problem zu lösen habe ich alleMObs, in denen Telegramme empfangen
werden direkt nach dem Initialisieren des CAN-Controllers aktiviert.
Erst danach werden Telegramme versendet. Wenn ein Telegramm empfangen
wurde, muss das zugehörige MOb sofort wieder den Empfang aktivieren,
bevor ein Telegramm versendet werden kann.
Diese Lösung funktionierte dann Fehlerfrei. Danach habe ich das Thema
nicht weiter verfolgt.
Mfg Christian
Hallo Christian,
danke erst einmal für die schnelle Antwort. Ein paar Worte zu meinem
CAN-Stack: Ich verwende lediglich 2 MObs: MOb0 dient als Empfänger (der
Filter lässt alle Nachrichten durch, die Filterung erfolgt per Software)
und MOb1 dient als Sender.
Empfangen wird per Interrupt.
Beim Senden wird das MOb1 zunächst deaktiviert, dann neu eingerichtet
und anschließend wieder aktiviert um zu Senden.
Um auf deine Lösung einzugehen: Die Aktivierung des einen Empfangs-MObs
erfolgt einmalig zu Beginn. Alle Sendungen werden erst anschließend
ausgeführt.
Leider habe ich trotzdem das Problem des "sterbenden Empfängers".
Grüße,
Holger
Hallo zusammen,
ich glaube, ich habe eine Lösung gefunden.
Im Errata des Datasheets findet sich unter Rev C ein Eintrag, der das
Problem zwar nicht 100% trifft, aber dessen Work-around zu funktionieren
scheint:
Ich habe das MOb 14 als "Dummy-Empfänger" eingestellt. Es lässt also
auch alle eigehenden Nachrichten durch. Durch die interne Priorisierung
bekommt es nur eine Botschaft, wenn kein anderes Empfangsregsiter
momentan bereit ist. In meinem Fall heißt dass: mein einziger Empfänger
MOb0 ist momentan nicht bereit.
Der Nachteil: ich verliere (zumindest ist der Minimal-Implementierung
aus dem Datenblatt) hin und wieder eine Botschaft. Das ist bei meiner
speziellen Anwendung allerdings egal!
Die neue Konfiguration lief jetzt über nacht (ca. 16 Stunden) problemlos
durch.
Ich hoffe das hilft dem Einen oder Anderen!
Grüße,
Holger