Hallo, ich würde gerne erfahren, was denn der Vorteil der Mailbox gegenüber eines FIFO beim Empfang von CAN Messages ist. Beim Renesas Synergy habe ich nur die Mailbox zur Verfügung, welche aber nur eine Nachricht jeweils aufnehmen kann. Wie geht man damit um, dass keine Nachrichten verloren gehen, wenn diese einmal schneller eintreffen, als sie verarbeitet werden? Ich habe das Problem, dass die Nachricht, welche noch nicht verarbeitet wurde, einfach überschrieben wird. Damit ist die erste Nachricht für den sendenden CAN Controller angekommen, aber sie kann nicht mehr vom Programm auf der Empfangsseite gesehen werden. Ich habe, um das zu vermeiden, die gesamte CAN Bus Auswertung in der ISR für den Empfang einer Message implementiert, was aber nicht im Sinne des Erfinders sein kann.
Du könntest im Interrupt Handler auch einfach die komplette CAN Message in einen FIFO packen, um dessen Daten später in der Hauptschleife zu verarbeiten.
Mailbox ist für zyklische Nachrichten, wo immer der aktuelle Status gesendet wird. Deine SW guckt da in gewissen Abständen vorbei und findet immer den neuesten Zustand vor. Nachgucken und Aktualisieren sind unabhängig und müssen nicht mit der gleichen Abtastrate erfolgen. Hast Du im Auto für Zustandvariablen wie "Licht an" oder "Gaspedal 25% getreten". Fifo ist für Nachrichten wo keine verpasst werden soll. Die kommen der Reihe nach rein und werden der Reihe nach abgearbeitet. Hast Du im Auto für Diagnosebotschaften, Firmwareupdates und das Krypto-Geraffel. Wenn Du kein Fifo in HW hast musst Du das in SW machen. D.h. beim Befüllen der Botschaft einen Interrupt erzeugen, und in dessen Routine die Daten in Deine Liste umkopieren. Die Liste abarbeiten macht dann die SW in Ruhe im Hauptprogramm.
Dann werde ich wohl um einen Fifo nicht herumkommen. Die Frage ist nur, wie ich den am besten implementiere. Ganz kapiert habe ich das Prinzip noch nicht. Ich muss ja ein struct, welches die ID, die Daten und die Länge des Datenwortes enthält, erstellen. Kann ich ein Array aus structs erstellen? Die Größe des Puffers wird durch die Anzahl structs vorgegeben. Die Nachricht muss jedesmal soweit wie es geht nach vorne geschoben werden wie es geht, und zwar auch dann, wenn keine Nachricht nachkommt. Das heißt, jedesmal, wenn eine Nachricht aus dem Puffer gelesen wird, muss alles eine Position nach vorne rücken. Wenn nichts nachkommt, muss trotzdem geschoben werden und die ausgelesenen Datenfelder werden als unbelegt gekennzeichnet. Dazu bräuchte ich wohl ein weiteres Element im struct. Dann muss ich irgendeine Fehlerbehandlung haben, wenn der Puffer voll ist. Ich habe noch nie mit Puffern gearbeitet und weiß deshalb nicht, ob ich mit meinem Gedankengang auf dem richtigen Weg bin. Vielleicht hat ja hier jemand schon einmal genau diese Aufgabe gelöst. Ich wäre sehr dankbar, wenn mir jemand hilft, dass der Knoten endlich platzt.
Guck dir mal an wie Ringbuffer implementiert werden. Da werden nur Zeiger geschoben, keine riesen Datenmengen umkopiert.
Der mailboxmode wird meist bei Echtzeisystemen benutzt. Im Automobilbereich z.B. Da ist die Software in Zeitscheiben aufgeteilt, die alle 10ms oder alle 20ms laufen. Somit wird in einem festen Interval gesendet und auf Empfängerseite ebenfalls in einem festen Interval in der mailbox nachgesehen. Da Sender/Empfänger nicht synchron laufen, kann hin und wieder mal eine Nachricht verloren gehen. Die Systeme können damit aber umgehen. Wenn Datenprotokolle laufen sollen (ISO15765, ISO11783...) wäre der Ringbuffer mode besser, weil Datenverlust zum Protokollabbruch oder Paketwiederholung führt. Viele Prozessoren haben die mailboxes gleich eingebaut. Den Ringbuffermode unterstützt bspw. der SJA1000, ein externer CAN Controller. Der kann aber soweit ich erinnere nur den Ringbuffer mode. Ich weiß nicht, ob es Prozessoren gibt, die beides parallel können, mailbox mode und ringbuffer mode.
Im Mailbox mode konfiguriert man die mailbox so, dass sie eine bestimmte Botschaft empfängt oder eben eine bestimmte Gruppe. Die Gruppe wird anhand von CAN-ID & AcceptanceMask festgelegt. So weiß der Controller sofort, was er mit der Botschaft in Mailbox X machen muss. Im Ringbuffer mode kann man das theoretisch zwar auch machen, aber der Ringbuffer mode wird meist benutzt, um erstmal im Interrupt alles zu empfangen, und später die empfangenen Daten den entsprechenden Kanälen zuzuordnen. Mit diesem Modus kann man bspw. dynamisch zur Laufzeit beliebig virtuelle CAN Kanäle gemäß OSI Schichtenmodell instanziieren.
Soweit, so gut. Die Mailbox ist also eine Art Filter, wo eine Vorauswahl getroffen wird anhand der ID, sodass für jede Mailbox eine eigene ISR die Verarbeitung der eingegangenen Messages übernimmt. Trotzdem sehe ich Probleme, wenn Messages für eine Mailbox direkt hintereinander eintreffen, sodass entweder die erste Nachricht überschrieben wird oder die letzte verworfen wird. Wenn ich jetzt richtig liege, gilt eine Message für den sendenen CAN-Controller aber dann trotzdem als übermittelt. In dem Moment habe ich keinen Puffer, welcher die Messages bis zur Verarbeitung sicher aufbewahrt. Ich frage mich, wo das Geheimnis liegt, dass die Nachrichten lückenlos erfasst werden und das Programm trotzdem performant läuft.
Hi CAN in seiner Ursprungsidee (vor über 30 Jahren) sollte die dicken Kabelbäume im KfZ ersetzen. Es wurden also dazu verwendet Signale (z.B. Drehzahl, Blinker, Hupe usw.) auf einer Leitung zu multiplexen. Es wird vereinbart das auf dem Identifier 0x123 in Bytes 6-7 die Drehzahl übertragen wird. Man konfiguriert also die Mailbox einmal auf diesen Identifier und kann dann immer in den Bytes 6-7 die aktuelle Drehzahl abholen ohne sich um den CAN-Controller kümmern zu müssen. Es gibt dann kein "Nachricht verpassen" weil die Information immer die gleiche ist. Das gleiche System kann man heute bei CANOpen noch erkennen. PDOs haben dort auch eine fest Zuordnung von CAN-ID zu Daten wenn der Bus fertig konfiguriert ist. CAN wird heute natürlich für weitaus mehr benutzt wo der Mailboxbetrieb nicht immer passt. Desswegen haben neuere CAN-Controller eben einen FIFO Mode. Matthias
Asterix schrieb: > Beim Renesas Synergy habe ich nur die Mailbox zur Verfügung, welche aber > nur eine Nachricht jeweils aufnehmen kann. Das Datenblatt des kleinen S124 sagt auf Seite 723: Message box: 32 mailboxes, with two selectable mailbox modes: Normal mode: 32 mailboxes independently configurable for either transmission or reception FIFO mode: 24 mailboxes independently configurable for either transmission or reception, with remaining mailboxes used for receive and transmit 4-stage FIFOs. Es gibt also reichlich davon, da kann man eigentlich keine Nachricht verpassen.
Μαtthias W. schrieb: > 0x123 in Bytes 6-7 die Drehzahl > übertragen wird. Vielleicht ist die Drehzahl hier ein unkritisches Beispiel. Trotzdem wird dieses Signal regelmäßig übertragen und da sind wir wieder an dem Punkt, dass zwei hintereinander eintreffende Nachrichten kollidieren könnten. Interessanter wären z.B. Steuerbefehle oder sogar ein kritisches Stop-Signal (bspw. für eine Maschinensteuerung), welches keinesfalls ausgelassen werden darf; was sofort zuverlässig verarbeitet werden muss, egal wie schnell nachfolgende Nachrichten eintreffen.
Μαtthias W. schrieb: > Es gibt dann kein "Nachricht verpassen" weil die Information immer die > gleiche ist. > Das gleiche System kann man heute bei CANOpen noch erkennen. Das ist auch im Fahrzeug noch weitgehend so. Asterix schrieb: > Vielleicht ist die Drehzahl hier ein unkritisches Beispiel. Trotzdem > wird dieses Signal regelmäßig übertragen und da sind wir wieder an dem > Punkt, dass zwei hintereinander eintreffende Nachrichten kollidieren > könnten. Das stört aber nicht, da mich eine frühere Drehzahl nicht interessiert, sondern nur der aktuelle Wert. > Interessanter wären z.B. Steuerbefehle oder sogar ein kritisches Stop- > Signal (bspw. für eine Maschinensteuerung), welches keinesfalls > ausgelassen werden darf; was sofort zuverlässig verarbeitet > werden muss, egal wie schnell nachfolgende Nachrichten eintreffen. Das würde ja nur zum Problem führen, wenn danach nochmal die gleiche Nachricht kommt, wo aber das Stop-Signal nicht mehr gesetzt ist. Davon abgesehen könnte auch einfach so (z.B. durch ein externes Störsignal) eine Botschaft ausfallen. Den Fall, dass mal eine Botschaft fehlt, muss man also sowieso berücksichtigen.
Rolf M. schrieb: > Den Fall, dass mal eine Botschaft > fehlt, muss man also sowieso berücksichtigen. Wie würdest Du das sinnigerweise anstellen?
Asterix schrieb: > Rolf M. schrieb: >> Den Fall, dass mal eine Botschaft >> fehlt, muss man also sowieso berücksichtigen. > > Wie würdest Du das sinnigerweise anstellen? Kommt drauf an. Bei dem Beispiel mit der Drehzahl oder dem Stop-Signal kann man die Daten einfach zyklisch senden, mit einer Zykluszeit, die kurz genug ist, dass ein Ausfall unkritisch ist. Im Automobilbereich ist das üblich. Wenn man dagegen keine Signale an festen Stellen in der Botschaft hat, sondern andere Daten übertragen will, wie z.B. eine Firmware, dann muss man noch ein Transportprotokoll drauf setzen, das eine korrekte und vollständige Übertragung sicherstellt, wie das schon genannte ISO15765. Auch das wird im Automobilbereich genutzt.
:
Bearbeitet durch User
Das mit der Zykluszeit sollte hinzubekommen sein. Rolf M. schrieb: > Im Automobilbereich ist > das üblich. Es hat sich für mich herausgestellt, dass gerade im Bereich der Automobiltechnik viel Geheimniskrämerei herrscht und ich finde, dass es nicht einfach ist, an konkrete Informationen oder Codebeispiele zu kommen, anhand derer die sichere Funktionsweise nachvollziehen lässt. Gibt es dazu beispielhaften (oder realen) Code, um diese Zusammenhänge und die dahintersteckende Komplexität, gerne auch im Zusammenspiel mit einem RTOS, besser zu vestehen?
Asterix schrieb: > (...) Interessanter wären z.B. Steuerbefehle oder sogar ein > kritisches Stop-Signal (bspw. für eine Maschinensteuerung), welches > keinesfalls ausgelassen werden darf; was sofort zuverlässig verarbeitet > werden muss, egal wie schnell nachfolgende Nachrichten eintreffen. Auf dem CAN werden keine Steuerbefehle übertragen, sondern Zustände. Da hast Du irgendwo eine Information, die die Zustände "Maschine läuft" und "Maschine stop!" enthält. Diese Information wird regelmäßig gesendet. Deine Software guckt in gewissen Zeitabständen in die Mailbox und findet da immer den neuesten Zustand vor. Wieviele Nachrichten in der Zwischenzeit angekommen sind interessiert keinen, nur die neueste (aktuelle) ist relevant. Deine Armbanduhr sagt Dir auch nicht immer Bescheid wenn der Controller eine neue Zeitanzeige berechnet hat. Sie zeigt einfach den neuesten Wert an. Und wenn Du irgendwann mal draufguckst siehst Du den aktuellen Zustand, ungeachtet der Vorgeschichte. Wenn man mit so einem System Daten übertragen will, wo jede einzelne Botschaft zählt, dann geht das nur mit einem geeigneten Handshake. Dafür sind Transportprotokolle da. Wie bei besseren Stoppuhren mit Zwischenzeit-Anzeige: "ja, ich habe den Wert gesehen, gib mit bitte den nächsten".
Dann liege ich mit meinem Ansatz scheinbar gar nicht so falsch. Dann könnte ich doch die ankommenden Nachrichten anhand ihrer ID in ein jeweils entsprechendes Struct kopieren, welches auch ein Flag enthält, ob die Nachricht neu oder schon abgearbeitet ist. Jedesmal, wenn die selbe Nachricht erneut eintrifft, wird der Inhalt überschrieben und das Flag gesetzt, welches von der entsprechenden Funktion ausgewertet wird und nach Bearbeitung der Nachricht zurückgesetzt wird. Dann habe ich zumindest die Nachrichten auf verschiedene Speicherstellen verteilt und vor Überschreiben durch "artfremde" Nachrichten geschützt. Könnte mein Vorhaben funktionieren?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.