Eingebettete Systemaufgabenplanung für die Datenerfassung in einem CAN-Netzwerk

Ich kämpfe mit dem Konzept, wie ich meine Aufgaben planen soll.

Mein Setup: STM32F103 an CAN angeschlossen. Das Messen mit einem Lidar V3-Modul kommuniziert über I2C und verteilt diese Messung dann auf dem CAN

Interrupt 1 ist ein 1-ms-Timer-Interrupt, um das Senden von Nachrichten auf CAN zu initiieren

Interrupt 2 ist beim Empfang einer CAN-Nachricht aktiv

Ich muss auch ein Register über I2C auf der LIDAR-Einheit abfragen, um sicherzustellen, dass die Messung abgeschlossen ist, bevor ich dann I2C verwenden kann, um das Entfernungsregister zu lesen, Codeausschnitt unten gezeigt

        status = CheckLidarStatus();

        while ((status & LIDAR_BUSY) == LIDAR_BUSY)
        {
            status = CheckLidarStatus();
        }

Was meiner Meinung nach der richtige Ablauf ist, den mein Programm nehmen sollte, wird unten gezeigt:

Fluss von

Meine Hauptanliegen sind:

  1. Erscheint der Flow als logischer Weg, um dies anzugehen?

  2. Wenn ich den Timer-Interrupt (statt RX int) für die CAN-Übertragung priorisiere, wirkt sich dies negativ auf das CAN-Netzwerk aus, dh die empfangenen CAN-Nachrichten werden nicht rechtzeitig genug behandelt?

  3. Wenn einer der Interrupts während der I2C-Kommunikation aktiv ist, führt dies dazu, dass die I2C-Kommunikation "umfällt"?

  4. Ist es akzeptabel, in einer While-Schleife zu sitzen und darauf zu warten, dass der Checklidar-Status als nicht beschäftigt zurückkommt, oder gibt es einen besseren Weg, dies zu tun?

Welche Geschwindigkeit des CAN-Busses? 1-ms-Intervall ist sehr schnell für den CAN-Bus.
@ Jeroen3 500.000 Baudrate, aus meinen Berechnungen geht hervor, dass 250 us pro Frame-Nachricht im EXT-Format einen Overhead von 750 us ergeben. Was wäre eine typischere Aktualisierungsrate für die CAN-Übertragung?
Als schnell gilt ein Intervall von 100 ms. Wichtige Standards (z. B. j1939) spezifizieren oft, dass Nachrichten nicht innerhalb von 100 ms wiederholt werden dürfen. Also ja, vielleicht 10 ms. Aber 1 ms, definitiv nicht in einem Netzwerk, in dem Sie nicht alle Knoten steuern.
@ Jeroen3 okay, brillant, danke für die Hinweise dazu!
@ Jeroen3 10 ms ist ziemlich normal. 100 ms sind Müll, so lange Verzögerungen können Sie in einem CAN-Bus zur Maschinensteuerung nicht verwenden. Wenn J1939 Intervalle von 100 ms spezifiziert hat, dann sollte J1939 nicht in Fahrzeugen verwendet werden. Da dies jedoch der Fall ist, glaube ich nicht, dass 100-ms-Intervalle obligatorisch sein können.
@Lundin Es ist eine Referenz, J1939 ist nicht sehr streng definiert. Sie können kleinere Netzwerke erstellen. Es liegt schließlich am Systemintegrator.

Antworten (2)

  1. Ja, erscheint mir logisch. Wie lange darf das Lidar-Peripheriegerät jedoch maximal beschäftigt sein? Wenn das länger als 1 Millisekunde ist, könnten Sie eine Sendegelegenheit verpassen. Vielleicht sollte der Busy-Fall einfach die gelesenen Daten überspringen, anstatt zurück zu schleifen, um den Status abzufragen.

  2. Ja, der Interrupt-Handler mit niedrigerer Priorität wird abgeschaltet, während der Interrupt-Handler mit höherer Priorität läuft. Wenn der Timer-Interrupt-Handler mit höherer Priorität länger läuft, als das CAN-Peripheriegerät benötigt, um genügend Nachrichten zum Überlaufen zu erhalten, würden Sie Nachrichten verlieren. Deshalb ist es eine gute Faustregel, Interrupt-Handler kurz zu halten. Und wenn Ihr Timer-Interrupt nur ein Flag setzt, bezweifle ich, dass Sie ein Problem haben werden.

    Eine andere Möglichkeit, dies zu berücksichtigen, ist die Strafe, wenn einer der Interrupt-Handler durch den anderen verzögert wird. Wenn der CAN-Interrupt durch den Timer-Interrupt verzögert wird, würden Sie der CAN-Antwort eine Verzögerung hinzufügen oder im schlimmsten Fall eine Nachricht verwerfen. Wenn der Timer-Interrupt durch den CAN-Interrupt verzögert wird, würden Sie dem Timer-Interrupt Jitter hinzufügen. Im schlimmsten Fall würde eine Millisekunde ausfallen, aber dafür müsste der CAN-Interrupt länger als eine Millisekunde laufen. Was ist also weniger wünschenswert für Ihre Anwendung, ein wenig Verzögerung oder ein wenig Jitter?

  3. Es ist zweifelhaft, dass jeder Interrupt die I2C-Kommunikation unterbrechen würde. Sie verwenden wahrscheinlich ein I2C-Controller-Peripheriegerät, das Bits größtenteils unabhängig von der CPU sendet / empfängt. Der I2C-Controller taktet weiterhin nach Bedarf Bits ein und aus, ohne von den Interrupts beeinflusst zu werden. (Wenn Sie jedes Bit bit-bangen würden, hätte dies eine größere Auswirkung, da einzelne Takte durch einen unabhängigen Interrupt gedehnt werden könnten. Aber selbst das ist aufgrund der synchronen Natur von I2C nicht unbedingt ein Problem. Das Slave-Gerät sollte dies nicht tun ' Es ist egal, ob die I2C-Taktimpulse verlängert werden.)

  4. Es kann akzeptabel sein, den LIDAR-Status abzufragen. Wenn Sie nichts anderes für die CPU zu tun haben, was schadet es dann? Wenn das Lidar-Peripheriegerät jedoch über eine Art "Daten bereit" -Interrupt verfügt, können Sie diesen Interrupt aktivieren und auf den Interrupt warten, anstatt den Status abzufragen.

1. Ich werde das versuchen, indem ich die Lesedistanz überspringe, anstatt den Status abzufragen. Es wird nicht wirklich erwähnt, was passieren würde, wenn ein Lesebefehl angewendet würde, während sein Status beschäftigt ist. Ich stelle mir vor, es würde mir den Reg-Wert geben, aber nicht aktualisiert, bis die Messung abgeschlossen ist.
2. Das ist wirklich hilfreich, danke! 3. Ja, es ist ein Peripheriegerät, es ist nicht die Dehnung, über die ich mir Sorgen gemacht habe, es ist eher die Lücke zwischen einem Stopp- und Startpunkt, die zu groß ist, mit der ich mir Sorgen gemacht habe. Zum Beispiel sende ich zum Lesen die Adresse dessen, wovon ich lesen möchte, und stoppe dann I2C. Dann habe ich I2C erneut mit der Adresse des Geräts im Lesemodus gestartet, um die im Register enthaltenen Daten zu erhalten. Die Lücke zwischen Start und Stopp war meine Sorge, da das Datenblatt nicht darauf anspielt, wie schnell dies geschehen muss
4. Das Lidar ist nicht in der Lage, einen Interrupt zu generieren, da es über I2C verbunden ist, und es generiert keine automatische I2C-Kommunikation, um anzuzeigen, dass die Messung abgeschlossen ist. Wie in meinem ersten Kommentar erwähnt, haben Sie mir jedoch den Gedanken gegeben, dass ich die Überprüfung des Status insgesamt überspringen und akzeptieren kann, dass ich die Entfernungsreg häufiger lesen kann, als sie tatsächlich aktualisiert. Das Datenblatt für das Lidar ist jedoch kurz und zeigt nicht die Auswirkungen des Lesens von anderen Registern als dem Status, während es damit beschäftigt ist, eine Messung durchzuführen. Ich denke aber es sollte passen!
Vielen Dank für die Antwort, die sehr hilfreich ist und mein Verständnis insgesamt verbessert hat !! Ich denke, Sie haben mir genug gegeben, um das jetzt zu vollenden.

Es liegt in der Natur von CAN, dass beim Versuch, eine Nachricht zu senden, Kollisionen mit Nachrichten mit höherer Priorität auftreten können, die Sie empfangen und verarbeiten müssen.

Ihr Vorschlag zeigt extrem einfache ISRs, die lediglich Flags setzen, wobei die gesamte eigentliche Arbeit in einem einzigen Hintergrundthread (Nicht-ISR) ausgeführt wird.

Ich kenne die Details des CAN-Controllers des STM32 nicht und insbesondere nicht, wie autonom er sein könnte, aber Ihr Vorschlag scheint in Bezug auf dieses Problem unzureichend zu sein.

Es ist autonom genug, dass Sie nur eine Mailbox als sendebereit markieren müssen.
Vielen Dank für Ihre Antwort, nur Nachrichten, die für diesen Knoten bestimmt sind, müssten vom Prozessor verarbeitet werden, was erfordern würde, dass die enthaltenen Daten über i2c (Einstellungsänderung am Modul) auf das Lidar angewendet werden. Würden Sie empfehlen, diesen I2C-Befehl in die ISR einzufügen?
Nein, definitiv nicht! Der CAN-Empfangs-ISR sollte alle erforderlichen Schritte unternehmen, um die CAN-Schnittstelle für den Empfang der nächsten Nachricht bereit zu machen, aber alle anderen Arbeiten, wie z. B. die Kommunikation mit dem LIDAR, sollten auf einen Hintergrund-Thread verschoben werden.
ah okay ich verstehe was du meinst entschuldigung. Mein RX INT wird nur aktiviert, wenn eine Nachricht für diesen Knoten empfangen wird. Um den Empfänger wieder für den Empfang geeigneter Nachrichten bereit zu machen, muss ich den FIFO freigeben, was bedeutet, dass ein Bit gesetzt wird, aber dies kann nur nach dem Lesen der Daten erfolgen. Was ich, wie Sie vorschlagen, in den Hintergrundthread verschieben werde! Vielen Dank
Irgendwie drücke ich mich nicht klar aus. Wenn Sie Daten aus dem FIFO des CAN-Controllers lesen müssen, um ihn für den Empfang der nächsten Nachricht vorzubereiten, dann sollten Sie dies unbedingt im ISR tun, die Daten in einen geeigneten Speicherpuffer legen und dann ein Flag oder was auch immer dafür setzen Hintergrundthread. Die Übertragung dieser Daten über die I2C-Schnittstelle ist jedoch zeitaufwändig, was NICHT im ISR erfolgen sollte. Stattdessen sollte der Hintergrund-Thread die Daten aus dem Speicherpuffer lesen und sie in beliebiger Geschwindigkeit an das LIDAR übertragen.
Wenn ich ein solches Projekt durchführen würde, hätte ich einen "Thread", der sich nur der Verwaltung der I2C-Schnittstelle zum LIDAR widmet. Es würde nach Nachrichten suchen, die vom CAN-Bus kommen, und sie an das LIDAR senden. andernfalls würde es die Entfernungsdaten abrufen. Dies macht es einfach, den Konflikt zwischen den beiden Verwendungen der I2C-Schnittstelle zu verwalten.
Ich denke, es liegt eher an meinem mangelnden Verständnis in Bezug auf CAN und Terminplanung als an Ihrer Klarheit, Ihr letzter Punkt ist jedoch klar und sehr hilfreich (+1)