Guten Morgen allerseits,
ich habe folgendes Problem:
Zwei Geräte tauschen über einen CAN Bus Nachrichten aus. Wenn eine
Nachricht in die Mailbox geschrieben wird, dann wird in einer ISR ein
Flag gesetzt, dass eine neue Nachricht vorliegt. In einer Sequenz aus
If-Abfragen in meiner Main-Loop wird dieses Flag abgefragt und wenn es
TRUE ist, werden die Nachrichten auf ID und Inhalt gefiltert und der
weiteren Verarbeitung zugeführt. Danach wird das Flag zurückgesetzt.
Wenn ich die Nachrichten einzeln versende, funktioniert das tadellos.
Wenn aber zyklisch, sagen wir alle 100 ms eine Nachricht versendet wird
und noch zusätzliche Nachrichten versendet werden, kommt es oft zu dem
Problem, dass die zweite Nachricht die erste Nachricht im Empfänger
überschreibt, bevor sie verarbeitet werden kann. Dann gibt es zwei
möglichkeiten: die erste ist, dass die erste Nachricht einfach nicht
erkannt wird, weil mein Programm langsamer ist, als die Mailbox die
Daten empfängt. Dann erhalte ich zunächst nicht unbedingt eine
Fehlermeldung, die Nachricht kommt aber nicht in der IF-Abfrage an. Die
zweite Möglichkeit ist, dass ich den Error-code
"SSP_ERR_CAN_DATA_UNAVAILABLE" erhalte. Das führt dann zum Abbruch der
Verbindung. Der Sender wird danach seine Nachricht nicht mehr los, was
wiederum zum Bus overload führt. Kurz zu meinem verwendeten System:
Renesas Synergy S124 und S3A7. Ich bin mir sicher, dass die Art und
Weise, wie ich die Kommunikation aufgebaut habe, sehr rudimentär ist und
deshalb die Fehler auftreten. Woanders funktioniert es ja auch.
Allerdings ist es so, dass ich es schwierig finde, genau zu diesem Thema
brauchbare, respektive verständliche, Informationen zu erhalten, wie
eine Kommunikation über CAN aufgebaut sein muss, damit dieses Problem
nicht auftritt. Schließlich mache ich mir so sämtliche Vorteile des CAN
busses zunichte. CAN-OPEN wäre natürlich eine Alternative, aber es muss
ja auch anders, also zu Fuß, gehen. Ich bin mir sicher, dass hier der
eine oder andere Experte ist, der mir auf den richtigen Weg helfen kann.
Vielen Dank!
Haudrauf schrieb:> kommt es oft zu dem> Problem, dass die zweite Nachricht die erste Nachricht im Empfänger> überschreibt, bevor sie verarbeitet werden kann.
Du darfst einen Puffer natürlich nicht freigeben, bevor er verarbeitet
wurde. In der Regel haben CAN-Controller mehrere Puffer, d.h.
Nachrichten landen automatisch im nächsten freien.
Man kann aber auch eine FIFO im RAM einrichten und die Nachrichten per
Interrupt oder DMA dort ablegen.
Normalereise besitzt die Hardwareeinheit deines CAN Controllers mehrere
Empfangspuffer, meist 3-5. Bei Full CAN sind dann auch mal z.B. 32,
diese werden dann meist als Mailboxen verwendet, d.h. in jede
Empfangsbox wandert nur eine Nachricht mit einer passenden
(konfigurierten) ID.
Gehen wir mal davon aus, dass du dieses Feature nicht benutzt, dann
würde ich so vorgehen:
Nachricht empfangen, Flag des belegten Puffers setzen und in der
Hauptschleife alle sagen wir mal 10ms (hängt von dem ab, was auf dem Bus
los ist und wie hoch deine Baudrate ist) vorbei kommen und ALLE belegten
Puffer abarbeiten und wieder freigeben.
Christian G. schrieb:> Normalereise besitzt die Hardwareeinheit deines CAN Controllers mehrere> Empfangspuffer, meist 3-5. Bei Full CAN sind dann auch mal z.B. 32,> diese werden dann meist als Mailboxen verwendet, d.h. in jede> Empfangsbox wandert nur eine Nachricht mit einer passenden> (konfigurierten) ID.
Ja, bei mir sind es 32 Mailboxen. Davon benutze ich eine zum Senden,
eine zum Empfangen. D.h. die Mailbox kann genau eine Nachricht
speichern. Mir ist nicht bekannt, wie ich das anders konfigurieren
könnte.
Christian G. schrieb:> Nachricht empfangen, Flag des belegten Puffers setzen und in der> Hauptschleife alle sagen wir mal 10ms (hängt von dem ab, was auf dem Bus> los ist und wie hoch deine Baudrate ist) vorbei kommen und ALLE belegten> Puffer abarbeiten und wieder freigeben.
Meine Baudrate ist auf 500kbit/s eingestellt. Wie kann ich der Mailbox
denn mitteilen, dass sie nicht empfangen darf? Der Sinn folgndr
Einstellung ist mir auch noch etwas schleierhaft: overwrite mode und
overrun mode. Wann ist was auszuwählen?
Haudrauf schrieb:> Ja, bei mir sind es 32 Mailboxen. Davon benutze ich eine zum Senden,> eine zum Empfangen.
Der S124 besitzt ja sogar einen Hardware-FIFO-Mode für 24 Botschaften.
Da kann man fast nix mehr verpassen.
> Mir ist nicht bekannt, wie ich das anders konfigurieren könnte.
Das sollte dein Framework oder Beispielcode aber sagen.
Thomas F. schrieb:> Der S124 besitzt ja sogar einen Hardware-FIFO-Mode für 24 Botschaften
Ja, den habe ich im Manual auch gesehen. Ich verstehe allerdings nicht,
wie ich an das Register komme, um es zu Ändern.
Thomas F. schrieb:> Das sollte dein Framework oder Beispielcode aber sagen.
Genau das tut er leider nicht, ein CAN Framework gibt es nicht, nur
einen driver. Ich hätte mir davon auch mehr erhofft.
Haudrauf schrieb:> Mir ist nicht bekannt, wie ich das anders konfigurieren> könnte.
Das sollte im Manual Deiner CPU aber beschrieben sein.
Falls Dein Framework keine entsprechenden Funktionen bereit stellt, kann
man auch einfach die IO-Register direkt ansprechen.
Peter D. schrieb:> kann man auch einfach die IO-Register direkt ansprechen.
Dafür muss man aber wissen, wie...
Haudrauf schrieb:> Ich verstehe allerdings nicht,> wie ich an das Register komme, um es zu Ändern.
npn schrieb:> Dafür muss man aber wissen, wie...
Im Example-Ordner Deiner Compilerinstallation sollten Beispiele zu
finden sein. Die IO-Register und Bits heißen in der Regel genau so, wie
im Datenblatt.
Und mit #include<io.h> sollten sie dem Compiler bekannt sein.
Peter D. schrieb:> Die IO-Register und Bits heißen in der Regel genau so, wie> im Datenblatt.> Und mit #include<io.h> sollten sie dem Compiler bekannt sein.
Ja, in der S124.h sind die Register tatsächlich enthalten. Leider stehe
ich gerade auf dem Schlauch, wenn es darum geht, die entsprechenden bits
im Register zu setzen/zurückzusetzen. Ich finde nirgends eine Erklärung,
nach welchem Muster derartige Funktionsaufrufe aufgebaut sein müssen.
Nun, ich habe nochmal ein bisschen experimentiert und bin zu dem Schluss
gekommen, dass das Beispiel von Renesas offensichtlich in keiner Weise
praxistauglich ist. Ich habe die Routinen zur Filterung der Nachrichten
jetzt direkt in die ISR eingebaut. Jetzt gehen erstmal keine Nachrichten
verloren. Die Frage ist nur, wie weit man bei der Bearbeitung der
Nachrichten innerhalb der ISR gehen darf, ohne deren Ausführungszeit
unzulässig zu verlängern.
Wäre es auch denkbar, wenn ich mit ThreadX arbeite, die Nachrichten in
eine Message Queue zu schreiben und diese in einem anderen Thread zu
verarbeiten? Ich habe wenig Erfahrung in der Programmierung mit mehreren
Threads gleichzeitig. Der Vorteil wäre, dass ich die Größe der
Warteschlange einstellen kann. Ob es unter dem Strich aber ein Vorteil
ist, weiß ich nicht, da jeder Thread auch wieder einzeln durchlaufen
werden muss. Allerdings kann ein kurzzeitiges höheres
Nachrichtenaufkommen vielleicht kompensiert werden. Hm...