2016-04-15 10 views
1

Wann soll ich FreeRTOS auf so etwas wie Cortex-M3 verwenden Sperren zu verwenden? Es scheint klar zu sein, Multicore-Systeme zu verwenden, aber was ist mit Single-Core?FreeRTOS Schlösser und Aufgaben

Zum Beispiel habe ich zwei Aufgaben. Zuerst inkrementiere ich die Variable counter. Die zweite Aufgabe speichert den aktuellen Wert dieser Variablen, wenn ein Ereignis eintritt. Soll ich hier Schlösser benutzen? Kann der erste korrupte Wert, den die zweite Aufgabe speichert, zuerst?

+1

Ja. Unterbricht. Treiber. Verwenden Sie Sperren. –

+0

@MartinJames: Sperren in einem Interrupt-Handler? Klingt wie eine schlechte Idee. – Olaf

Antwort

2

Ja, Sie sollten Sperren Sie den Zugriff auf die gemeinsam genutzte Ressource zu schützen.

Sie können nicht sicher sein, dass die vom Compiler erzeugten Sequenz der gemeinsame Variable ist atomar zu lesen, könnte es so unsicher sein.

Wenn Sie etwas mehr hardcore sein möchten und möglicherweise Leistung gewinnen, können Sie verschiedene Möglichkeiten nutzen, um sicherzustellen, dass die Variable atomar zugegriffen werden kann. Siehe Kommentar.

+0

Es gibt '_Atomic' plus' stdatomic.h' mit Makros, deren Typen garantiert atomarfrei sind. Bei einem eingebetteten System '_Static_assert' sind die verwendeten Typen atomar gut akzeptabel. – Olaf

+0

@Olaf, damit ich 'stdatomic.h' von newlib ohne irgendwelche Tricks verwenden kann? –

+0

@LongSmith: 'stdatomic.h' ist nicht Teil der newlib, aber normalerweise der Compiler. Siehe den Standard. – Olaf

1

müssen Sie Schlösser verwenden gleichzeitigen Zugriff auf gemeinsam genutzte Objekte zu synchronisieren, würde das einfachste Szenario wie:

lock_t l; // defines a lock of your system 

// thread 1: 
lock(l); 
counter += 1; 
unlock(l); 


// thread 2: 
lock(l); 
do_something(counter); 
unlock(l); 
0

In Ihrem speziellen Beispiel, bei dem ein Leser ist und ein Autor (also nicht in der „allgemeinen“ Fall, und definitiv nicht in dem Fall, wo es mehrere Autoren gibt) dann würde ich vorschlagen, eine Sperre ist nicht notwendig, wenn die Variable geschrieben/gelesen wird, ist die natürliche Wortgröße der Architektur, und wird benötigt, wenn die Variable nicht das natürliche Wort ist Größe der Architektur.

In Ihrem Fall die Wortgröße 32 Bits, also wenn die Variable ein uint32_t ist, dann wird es atomar aktualisiert werden, und ein Schreiber und mehrere Leser ist sicher. Wenn auf der anderen Seite waren die Variable ein uint64_t dann wird es (geschrieben) in zwei separaten Zugängen aktualisiert werden, und Sie müssen den Leser nicht gewährleistet, auf die Variable zugreifen zwischen den beiden Updates, dies zu tun wäre eine beschädigte lesen (halber aktualisierter) Wert.

In FreeRTOS eine einfache Möglichkeit, dies zu tun, wäre also einen grundlegenden kritischen Abschnitt zu verwenden:

taskENTER_CRITICAL(); 
My64BitVariable++; 
taskEXIT_CRITICAL(); 

Die beste Methode hängt jedoch von der Häufigkeit des Ereignisses. Wenn das Ereignis "nicht zu schnell" ist, dann senden Sie den Wert von einer Aufgabe zu einer anderen mit einem queue, in welchem ​​Fall FreeRTOS kümmert sich um alle Nebenläufigkeit Probleme für Sie. Besser (schneller und weniger RAM), abhängig davon, was die empfangende Aufgabe macht, muss die Schreibaufgabe den Wert direkt an die empfangende Aufgabe senden, unter Verwendung einer direct to task notification.