auf die gemeinsamen Werte zu schreiben ich werde versuchen, Ihnen eine Antwort geben basierend auf den begrenzten Informationen, unter der Annahme:
- ein einfacher, Homebrew Scheduler verwendet wird Rufen Sie task1 und task2 auf der Basis einfacher Kriterien auf
- task1 und task2 laufen bis zum Abschluss (d. h. sie nicht präjudizieren)
- Daten ein Byte-Basis ist Strom (eine etwas andere Implementierung erforderlich, wenn Sie Pakete benötigen)
Was ich in der Regel versuchen, wenn eingebettete Systeme entwerfen, ist die Verwendung von Semaphoren zu minimieren und Modell lock-free Datenflüsse. Ich werde das unten illustrieren:
asynchronous (lock free) communication queues http://www.freeimagehosting.net/uploads/477741db06.gif Die ISRs können durch Verwendung einer threadsicheren FIFO-Warteschlange von Tasks entkoppelt werden. Ein Beispiel findet sich in http://msmvps.com/blogs/vandooren/archive/2007/01/05/creating-a-thread-safe-producer-consumer-queue-in-c-without-using-locks.aspx
Eine solche Implementierung (ohne Sperren) hat keine Betriebssystemabhängigkeiten und sollte trivial einfach zu unterstützen sein. Dies ergibt auch ein klares Hersteller-Verbraucher-Design, das frei von Deadlocks ist.
Angenommen, die Tasks werden von einem Home-Brewn-Scheduler ausgelöst, können Sie dort nach Ereignissen (nicht leerem FIFO) suchen. if (TRUE == fifo_filled (my_read_queue)) {invoke task 1}
Nun zur Synchronisation von task1 und task2. Wenn Task1 nur Daten erzeugt, kann derselbe Mechanismus verwendet werden: Wenn Sie eine Warteschlange (fifo) haben, in der Task1 Daten schreiben kann, die von Task 2 gelesen werden können, dann sind die Tasks entkoppelt. Auch dies kann in Ihrem Scheduler überprüft werden (if (TRUE == fifo_filled (task1_to_2_queue()) {invoke task2)}
Wenn Sie mehr benötigen (dh wenn Aufgaben nicht vollständig ausgeführt werden, sondern vorläufig sind) Sie ' Ich brauche einen Mechanismus, um zu synchronisieren.Optionen beinhalten: - verwenden Sie ein (freies) Betriebssystem oder einen einfachen Scheduler sowieso - brauen Sie Ihre eigenen (meine Erfahrung: sollte nur getan werden, wenn es so einfach ist wie eine for-Schleife und ein paar if-Anweisungen) - verwenden Sie einen einfachen Scheduler (viel leichter als ein komplettes RTOS) - Refactor Code um Task1 und Task2 in einem zu integrieren. In diesem Fall werden Sie den Scheduler effektiv in Ihren Anwendungscode einfügen.
Hinweis: Die Beispielfunktion, die ich in dieser Erklärung verwendet habe (fifo_filled()) ist nicht Teil des Beispielcodes. Es sollte true zurückgeben, wenn (lesen! = Schreiben) Der Beispielcode verwendet auch globale Variablen lesen und schreiben; Sie können entweder eine Funktion aufrufen, die mehrere Warteschlangen verwalten kann, oder Lese-/Schreib- und Puffervariablen in die Struktur verschieben und auf die Struktur in den Parametern verweisen.
Eine alternative Möglichkeit besteht darin, einen kritischen Abschnitt durch Interrupt-Sperre zu erstellen. Ich versuche jedoch, dies zu begrenzen, da es oft eine starke Systemkopplung erzeugt und der Code schwieriger zu verwenden ist.
An welcher Plattform arbeiten Sie? – Amber
Da die beiden ISRs dieselbe Priorität haben, können sie sich gegenseitig unterbrechen? Wenn nicht, benötigen Sie möglicherweise keine zusätzliche Synchronisierung. –
@Matthem - normalerweise ISRs deaktivieren die Interrupts, wenn sie eingeben. Aber das wäre gut zu überprüfen. – Robert