mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik curioses CAN problem (at90can128)


Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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..

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:


//can.c

ISR( CANIT_vect ){
  //captures all events, including reception and transmission complete

  //determine what has happened
  //first step: determine which m0b has caused an interrupt
  uint8_t mObNumber = 0;

  mObNumber = CANHPMOB >>4;

  CANPAGE = (mObNumber<<4); //select message object which caused the interrupt

  //second step: determine what event has occurred (rx or tx);
  if(CANSTMOB & (1<<RXOK)){ //reception OK interrupt
    //if there was a message received
      //clear receive interrupt flag
CANSTMOB &= ~(1<<RXOK);
setLedsToggled(1<<LED7);

    MessageObject message;
    uint8_t i;

    for(i = 0; i<8; i++){      //get the data
      message.messageData[i] = CANMSG;
    }

    message.messageID = 0;  //get the id
    message.messageID |=  ((uint16_t) CANIDT1<<8);
    message.messageID |=  ((uint32_t) CANIDT2);
    message.messageID >>= 5;


    //put that message into the buffer; if buffer is full; message will be lost
    if (putMessageInBuffer(message,&canBufferRec)){
      setLedsOn(1<<LED6); //geht nie an, es gibt nie einen buffer-overflow
    }

    CANCDMOB = (1<<CONMOB1);    //reconfigure mailbox for reception, standard ids

    while(!(CANCDMOB & (1<<CONMOB1))){  
      setLedsToggled(LED5);       //geht auch nie an, d.h conmob1 wird immer gesetzt
      CANCDMOB = (1<<CONMOB1);
    }

  }
  else if(CANSTMOB & (1<<TXOK)){ //transmission ok interrupt
    CANSTMOB &= ~(1<<TXOK);          //reset flag
      }
  else{  //something else, most likely an error

  }
//}
}

CanBuffer canBufferRec = {{}, 0, 0};

uint8_t putMessageInBuffer(MessageObject mIn, CanBuffer *b)
{
  uint8_t sregTemp = SREG;
  cli();

  uint8_t next = ((b->write + 1) & CAN_BUFFER_MASK);
  if (b->read == next){
    SREG = sregTemp;
    return 1; //buffer is full
  }
  b->data[b->write] = mIn;
  // *b.data[*b.write & BUFFER_MASK] = byte; // absolutely secure
  b->write = next;

  SREG = sregTemp;
  return 0;
}
uint8_t getMessageFromBuffer(MessageObject *mOut, CanBuffer *b)
{
  uint8_t sregTemp = SREG;
    cli();
  if (b->read == b->write){
    SREG = sregTemp;
    return 1;  //buffer is empty
  }
  *mOut = b->data[b->read];
  b->read = (b->read+1) & CAN_BUFFER_MASK;
  SREG = sregTemp;
  return 0;
}

uint8_t getAMessage(MessageObject *mOut){
  uint8_t sregTemp = SREG;
    cli();
  return getMessageFromBuffer(mOut, &canBufferRec);
  SREG = sregTemp;
}


//in der can.h 
typedef struct {
  uint16_t messageID;
  uint8_t messageData[8];
  //uint8_t extendedId; //0 standardID, 1 extended
  //for now, always use standard IDs
}MessageObject;

typedef struct  {
  MessageObject data[CAN_BUFFER_SIZE];
  uint8_t read; // point to the index with oldest data
  uint8_t write; // points to empty index
} CanBuffer;


//in der Main.c

int main(void){
while(1){

if(!getAMessage(&m)){ //if there is an new Message available

      canData data;
      //data.e = m.messageData;
      uint8_t i = 0;
      for(i = 0; i<8; i++){
        data.e[i] = m.messageData[i];
      }

//in dem switch wird dann auch noch ein bisschen gerechnet; 
//die leds flackern eine Weile, bis eben das Mob nicht mehr arbeitet.

      switch (m.messageID) {
      case 0x792:{//ACC_T01
        setLedsToggled(1<<LED0);
        break;}
      case 0x793:{//ACC_T02
                setLedsToggled(1<<LED1);
        break;}
      case 0x6B5:{//RADAR_INFO1
                setLedsToggled(1<<LED2);
        break;}
      case 0x130:{//CLU_1
        
        setLedsToggled(1<<LED3);
        break;}

      case 0x131:{//CLU_2
                setLedsToggled(1<<LED4);
        break;}
      default:
        break;
      }
    }

}
}


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

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: tex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Michael Sch. (schmichael)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Christian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.