Forum: Mikrocontroller und Digitale Elektronik Atmel AT90CAN128 interrupt Problem, Puffer? Letzte Hilfe


von Timo (Gast)


Lesenswert?

Hallo,

ihr seid meine letzte Hoffnung.

Und zwar benützte ich wie oben angegeben einen Atmel AT90CAN128. Es 
werden 3 CAN Nachrichten über einen interrupt eingelesen.

So weit so gut.

Mein Problem: Alles funktioniert so lange die Nachrichten nur sporadisch 
kommen. Sobald die Daten aber mit einer Zykluszeit von ca. 30ms gesendet 
bzw. empfangen werden bleibt der yC hängen. Heißt es werden keine Daten 
mehr empfangen.

Beim debugen kommt der Fehler nicht vor, heißt, Programm läuft, Daten 
werden empfangen und verarbeitet.

Erste Hilfe meinerseits war über den Watchdog den yC immer wieder zurück 
zu setzen wenn keine Daten mehr empfangen werden, dies funktioniert nur 
zum Teil!

Wenn der yC sich resetet oder ich die Platine von Hand neustartet tritt 
zum teil der exakt selbe Fehler direkt wieder auf! Was ich allerdings 
beobachtet habe, häufig nur wenn auch zum selben Zeitpunkt (beim start) 
auch Daten auf dem CAN-Bus versendet werden.

Komisch ist auch noch, dass eine Nachricht noch eingelesen wird und zwei 
nicht mehr.


Nun meine Frage:

Woran kann das liegen? :-(

Besitzt der Atmel einen internen Buffer welcher direkt voll ist bevor 
die Daten verarbeitet werden können? Kann ich diesen löschen?

Kann ich auch nur jeden zweiten Interrupt auslösen?


Achso, während meinen Berechnungen deaktiviere ich den Interrupt.

Hoffe Ihr könnt mir helfen. Bin echt am verzweifeln da mit dem yC am 
Donnerstag Tests geplannt sind und wenn ich das Problem bis dahin nicht 
gefunden bzw. gelöst hab alles ins Wasser fällt :-(


Hoffe meine Erklärung war nicht ganz verwirrend :-)

Vielen Dank schon mal.


Gruß Timo

von holger (Gast)


Lesenswert?

>Achso, während meinen Berechnungen deaktiviere ich den Interrupt.

Dann sind deine Berechnungen bzw. möglicherweise Ausgaben zu den
Berechnungen zu lang. Sendest du irgendwas über UART und wartest
bis das weg ist? Oder gibst du was auf LCD aus?

von Timo (Gast)


Lesenswert?

Ja Ausgabe auf LCD und das Ergebnis der Berechnung als Nachricht über 
den CAN

Heißt wenn ich das richtig verstehe meinst du das meine Berechnung so 
lang braucht bis der Buffer voll ist!?

Was wäre eine Abhilfe wenn ich die Ausgabe auf dem LCD behalten wollen 
würde, bzw. wenn meine Berechnung zu lang dauern würde!?

Wenn ich mit CANoe mitlog habe ich eine durchschnittliche 
Berechnungszeit von ca. 2ms also weit weg von den 30ms ! :-(

Danke für deine Antwort!

von Frank K. (fchk)


Lesenswert?

Hallo!

Ich denke, Du machst da einen strukturellen Fehler.

Für jede einkommende CAN Message bekommst Du einen CANIT Interrupt 
(Vektor 19 an Adresse 0x0024). Wenn der kommt, mußt Du alle Message 
Objekte abklappern, ob und wo eine neue Message eingetrudelt ist, 
eingegangene Messages aus dem Controller abholen, bearbeiten und das 
jeweilige Message Object wieder freigeben.

Das sieht dann ungefähr so aus:
1
// Imagecraft Interrupt-Deklaration
2
#pragma interrupt_handler   can_interrupt_rcv:iv_CAN
3
4
void can_interrupt_rcv(void)
5
{
6
  char can_irq=CANGIT;
7
  int mob_irq;
8
  char i,mob,st,cd;
9
10
  if (can_irq&BIT(7))
11
  {
12
    CANGIT=can_irq; // Interrupts zurücksetzen
13
    if (can_irq&BIT(6))
14
    {
15
      //Bus OFF IRQ, CAN neu initialisieren
16
      can_init();
17
    }
18
19
    mob_irq=CANSIT2|(CANSIT1<<8);
20
    if (mob_irq)  // Interrupt durch eine Message verursacht?
21
    {
22
      for(mob=0;mob<NB_MOB;mob++) // alle Messages durchgehen
23
      {
24
        if (mob_irq&&1)
25
        {
26
          CANPAGE=mob<<4;                // Message Object auswählen
27
          cd=CANCDMOB;
28
          st=CANSTMOB;
29
          if (st&BIT(5))
30
          {
31
            //!!! hier Message aus dem Controller abholen,
32
            //!!! auswerten und bearbeiten
33
          }
34
          CANCDMOB=0;
35
          CANSTMOB=0;                    // Status zurücksetzen
36
        }
37
        mob_irq>>=1;
38
      }
39
    }
40
  }
41
}

Ich habe den Code ziemlich zusammengestrichen. Mag sein, daß ich da zu 
viel gestrichen habe, aber so im Prinzip geht das.

Also: Du mußt JEDEN CANIT-Interrupt SOFORT behandeln.

Ich denke, Du bekommst darüber irgendwelche Werte. Die mußt Du dann in 
der Interruptroutine in einen Zwischenspeicher schreiben und wenn ein 
neuer Auswertezyklus beginnt dort herausholen.

fchk

von Timo (Gast)


Lesenswert?

Okay, würde bedeuten das ich nicht den Interrupt einfach deaktivieren 
kann.

Und das heißt bei jeder CAN-Nachricht kommt ein Interrupt, egal ob meine 
gesuchte ID oder nicht. (Dies war mir klar)

Aber so wie oben gezeigt mach ich es auch, ich speicher in meiner isr 
die Daten zwischen und dann kommt die Berechnung und danach die Ausgabe. 
Allerdings deaktiviere ich die Interrupts während der Berechnung.

Dies ist falsch wenn ich dein SOFORT richtig deute!?

Gehen denn die Daten sonst in einen Puffer?

Danke für deine Antwort.

Gruß Timo

von Frank K. (fchk)


Lesenswert?

Timo schrieb:
> Okay, würde bedeuten das ich nicht den Interrupt einfach deaktivieren
> kann.

Genau.

> Und das heißt bei jeder CAN-Nachricht kommt ein Interrupt, egal ob meine
> gesuchte ID oder nicht. (Dies war mir klar)

Eigentlich kommt nur ein Interrupt, wenn die Nachricht zu einer der 
definierten Akzeptanzmasken paßt, die Du natürlich vorher passend setzen 
mußt.

Interrupts können aber auch aus anderen Gründen auftreten (z.B. Bus 
Errors, die speziell am Anfang auftreten können, oder wenn der Bus mal 
aufgetrennt wird oder ein Gerät dazugeschaltet wird). Siehe Beschreibung 
von CANSTMOB im Datenblatt. Und die mußt Du natürlich auch alle 
behandeln. Wenn nicht, dann hängt es irgendwann. Mein Beispiel ist in 
der Hinsicht ziemlich gekürzt.

> Aber so wie oben gezeigt mach ich es auch, ich speicher in meiner isr
> die Daten zwischen und dann kommt die Berechnung und danach die Ausgabe.
> Allerdings deaktiviere ich die Interrupts während der Berechnung.
>
> Dies ist falsch wenn ich dein SOFORT richtig deute!?

Richtig. In der Interruptroutine würde ich aber keine Berechnungen 
machen.

> Gehen denn die Daten sonst in einen Puffer?

Du hast 16 Message Objekte (MOB). Zu jedem MOB gibt es einen Speicher 
für eine Nachricht, es gibt eine Akzeptanzmaske und einen Satz 
Status/Control-Register. Wenn Du bei einem MOB eine Akzeptanzmaske setzt 
und dieses MOB scharf schaltest, kann es eine Nachricht empfangen. EINE. 
Danach ist es voll und will geleert und zurückgesetzt werden. Niemand 
hindert Dich aber daran, mehrere MOBs gleichzeitig zu initialisieren und 
zum Empfang zu benutzen. Dafür hast Du ja so viele.

Zum Senden brauchst Du auch MOBs.

Die MOBs liegen alle auf einem gemeinsamen Adressraum. Durch Schreiben 
in CANPAGE schaltest Du auf ein bestimmtes MOB (Stichwort 
Bankswitching).

Mehr Pufferung gibts nicht. Also lautet die Strategie, Interrupts 
möglichst zeitnah zu behandeln und möglichst wenig in den Interrupts zu 
machen bzw die Interrupts möglichst kurz gesperrt zu lassen.

fchk

von Timo (Gast)


Lesenswert?

Okay, danke für deine Ausführliche Antwort. Dann hab ich ja morgen was 
zu tun :-)

Sollten noch Fragen auftauchen melde ich mich noch mal! Aber war schon 
mal super für die Hilfe!!

Danke Gruß

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.