Ich muss mich mit einem Zähler auseinandersetzen, der mir Häkchen für meine Bewerbung gibt. Der Zähler ist 32 Bit, also muss ich wissen, wie ich damit umgehen soll, wenn er umbricht. zum Beispiel:
Ich habe eine Funktion, die a zurückgibt (timestamp + shifttime) und ich habe eine andere Funktion, die 1 oder 0 zurückgibt, je nachdem, ob die Zeit abgelaufen ist oder nicht, aber es besteht die Möglichkeit, dass mein Zähler umbricht. Wie gehe ich damit um?
Vielen Dank für all die Antworten Jungs. Ich werde in dieser Bearbeitung näher darauf eingehen.
Ich verwende den STM32 Cortex-M3. Ich möchte den RTC-Zähler verwenden, um ihn als Häkchen für meine Anwendung zu verwenden, um Aufgaben zu planen, die in bestimmten Intervallen ausgeführt werden müssen. Die RTC kann einen Überlauf-Interrupt generieren, sodass es kein Problem darstellt, den Interrupt zu erkennen. Das Hauptproblem, das ich habe (oder zumindest denke ich, ist ein Problem), ist, wenn bestimmte Aufgaben einen bekommen (timestamp+shift) dh
int main( void )
{
FlashLedTimeStamp = ReturnCounter( 20 ); // currentcounter value + a shift of 20
StatusLedTimeStamp = ReturnCounter( 3 ); // currentcounter value + a shift of 3
// then later on ....
while(1)
{
/* other tasks could go here */
if( HasTimeElapsed( FlashLedTimeStamp ) )
{
/* do something and get another timestamp value */
FlashLedTimeStamp = ReturnCounter( 20 ); // currentcounter value + a shift of 20
}
if( HasTimeElapsed( StatusLedTimeStamp ) )
{
/* do something and get another timestamp value */
FlashLedTimeStamp = StatusLedTimeStamp( 3 ); // currentcounter value + a shift of 3
}
}
}
Nehmen wir an, dass mein RTC-Zähler nur 8 Bit lang ist, um die Mathematik zu vereinfachen.
Wenn mein aktueller Zähler bei 250 steht, wenn ich meine Zeitstempel erhalte, bedeutet das das FlashLedTimeStamp = 14 und StatusLedTimeStamp = 253 Wie würde ich überprüfen, um das zu sehen FlashLedTimeStamp abgelaufen??
Denken Sie daran, dass ich nicht unbedingt ständig überprüfe, wie hoch der aktuelle Zähler ist und ob bestimmte Zeitstempel abgelaufen sind oder nicht. Ich hoffe, das macht deutlich, was mein Problem ist.
Wie hoch ist Ihre Taktrate und bei welchem Wert beginnt der Zähler? Könnten Sie auch mehr Details über die Plattform bearbeiten, auf der Sie laufen (Betriebssystem, Chipsatz, Board-Hersteller usw.). Möglicherweise gibt es einige plattformspezifische Lösungen.
– A. Abgabe
22. Juni 2010 um 17:43 Uhr
Clifford
Es spielt keine Rolle, solange die Differenz zwischen Start- und Endzählung kleiner als 2 ist32, und vorzeichenlose 32-Bit-Arithmetik wird durchgeführt, selbst wenn der Zählwert den Umbruchpunkt überspannt. (Wenn Sie vorzeichenbehaftete Arithmetik verwenden, muss die Spanne kleiner als 2 sein32/2)
Zum Beispiel:
Start count: 0xfffffff
End Count: 0x00000002 (incremented through 0,1,2 - i.e. three counts)
End - Start == 0x00000002 - 0xfffffff == 0x00000003
Die richtige Antwort wird also erreicht, solange der Zähler die Bitbreite eines eingebauten Integer-Typs hat und dieser Typ verwendet wird. Wo vielleicht ein Zählerregister nicht die Breite eines eingebauten Integer-Typs hat, können Sie den gleichen Effekt erzielen, indem Sie die höherwertigen “Überlauf”-Bits maskieren.
Wenn Sie aus anderen Gründen die größere Anzahl benötigen oder wenn der Unterschied zwischen aufeinanderfolgenden Zeitstempeln zu groß ist, können Sie einfach eine andere Ganzzahl verwenden, die erhöht wird, wenn der Zähler niedrigerer Ordnung umbricht. Diese Ganzzahl bildet die höherwertigen Bits einer größeren Ganzzahl, sodass das LSB der zweiten Ganzzahl das 33. Bit dieser größeren Ganzzahl ist.
Dies ist die richtige Antwort. Führen Sie immer eine Subtraktion durch und vergleichen Sie mit Null, anstatt einen Rohvergleich durchzuführen. Die Subtraktion “behebt” das Wrapping-Problem.
– c.fogelklou
18. April 2017 um 13:50 Uhr
Wahrscheinlich stelle ich 3 Jahre später eine dumme Frage, aber warum muss der Unterschied zwischen Anfang und Ende weniger als 2 ^ 32/2 betragen. Zum Beispiel: Startzähler ist 0xfffffff und Endzähler 0xffffffe, alles wird gut funktionieren, der Unterschied zwischen Ende und Start wird korrekt sein. Prüfen godbolt.org/z/zvYWTjeo7.
– Ursescu Ionut
2. Dezember 2021 um 15:07 Uhr
@UrsescuIonut: Du hast recht. Ich bin eindeutig von einer vorzeichenbehafteten Arithmetik ausgegangen – aber beim Nachdenken weiß ich nicht warum. Die eigentliche Frage ist vielleicht, warum mich in dieser Zeit niemand korrigiert hat! Behoben.
– Clifford
2. Dezember 2021 um 23:07 Uhr
Wenn Sie zwei Zeitstempelablesungen vornehmen und Ihre erste Ablesung ist größer als die zweite, dann hat Ihr Zähler gewickelt. Das ist die grundlegende Art, einen Verpackungszähler zu erkennen.
Dies erkennt jedoch nicht, ob ein Zähler mehrfach umgebrochen ist oder wenn ein Zähler umgebrochen ist und zufällig größer als der erste Messwert ist. Da Sie gesagt haben, dass dies ein eingebettetes System ist und Ihre Beschreibung Ihren “Zähler” wie eine Uhr klingen lässt, prüfen Sie, ob Sie einen Interrupt so einstellen können, dass er ausgelöst wird, wenn die Uhr Null erreicht (so dass Sie jedes Mal, wenn die Uhr zurückgesetzt wird, einen Interrupt erhalten). Wenn dieser Interrupt ausgelöst wird, erhöhen Sie einen separaten Zähler. Dies sollte Ihrer Uhr effektiv zusätzliche Präzision verleihen und es Ihrem Zähler ermöglichen, ohne Probleme umzubrechen.
Vielleicht editieren, um zu sagen: „Wenn Sie zwei Zeitstempel lesen eines inkrementierenden Zählers/Timers…” — die letzten 3 (eingebetteten) Projekte, an denen ich gearbeitet habe, verwendeten a Countdown Timer, so dass Wraparound ist, wenn der 2. Wert größer als der erste ist. Beispielsweise zählt der eingebaute SYSTICK-Timer des ARM Cortex M3 bis 0 herunter und lädt dann mit einem bestimmten Wert neu, bevor er wieder herunterzählt. Gute Antwort.
– Dan
22. Juni 2010 um 22:41 Uhr
@Dan- Guter Punkt. Vielleicht wäre es klarer zu sagen: “Wenn Sie die (vorzeichenbehaftete) Differenz zwischen zwei Zeitstempeln berechnen und das Ergebnis das entgegengesetzte Vorzeichen zu dem hat, was Sie erwarten würden, wird der Zähler umgebrochen”.
– bta
22. Juni 2010 um 22:46 Uhr
Sie müssen die zum Umbrechen benötigte Zeit berechnen oder experimentell bestimmen und sicherstellen, dass Sie schneller abtasten.
– Oldtimer
23. Juni 2010 um 17:34 Uhr
Wandeln Sie das Ergebnis der vorzeichenlosen Subtraktion in ein vorzeichenbehaftetes um und vergleichen Sie es mit Null. Sollte Überlauf behandeln, wenn Sie es oft genug überprüfen (und Ihr Timeout weniger als die Hälfte des Bereichs Ihres Timers beträgt).
uint32_t timer( void); // Returns the current time value
uint32_t timeout;
timeout = timer() + offset;
// wait until timer() reaches or exceeds timeout value
while ((int32_t)(timeout - timer()) > 0);
Dies hat den Vorteil, dass nur ein uint32_t (Timeout) statt zwei (letzter Wert und Intervall) gespeichert wird.
– Osman-Pascha
10. August 2021 um 10:36 Uhr
Wenn Sie vorzeichenlose Variablen verwenden, um Ihre Zähler- und Timer-Ablaufzeit zu speichern, können Sie einfach diesen Test verwenden:
if (current_time - expiry_time < 0x80000000UL)
/* timer has expired */
Dies setzt voraus, dass Sie mindestens alle 0x80000000-Ticks auf Ablauf testen und dass Ihr längster Timer so eingestellt ist, dass er weniger als 0x80000000-Ticks in der Zukunft abläuft.
Die Frage ist etwas vage. Eine Möglichkeit besteht darin, ein Flag zu setzen, wenn Sie zum ersten Mal bemerken, dass die Zeit abgelaufen ist. Ein todsicherer Weg wäre, einen zweiten Zähler hinzuzufügen, der erhöht wird, wenn der erste Zähler überläuft. Dadurch wird tatsächlich ein 64-Bit-Zähler erstellt, der nicht überläuft.
Das ist nur Verzögerung der Ausführung. Schließlich wird auch der zweite Zähler überlaufen.
– mtvec
22. Juni 2010 um 17:46 Uhr
@Job: Ja, aber es ist eine höllische Verzögerung. Zwei hoch 64 ermöglicht 18.446.744.073.709.551.616 Ticks. Wenn jeder Tick eine Millisekunde ist, dann ergibt das eine Zeitspanne von etwas mehr als 580 Millionen Jahren.
– Torak
22. Juni 2010 um 17:55 Uhr
Sicher, alles, was ich sagen wollte, ist, dass dies keine wirkliche Lösung für das Problem ist.
– mtvec
22. Juni 2010 um 18:10 Uhr
Eine Lösung, die für Zeiträume von weniger als 580 Millionen Jahren funktioniert, ist keine “echte” Lösung des Problems? Warum nicht?
– Mike Pelley
22. Juni 2010 um 19:33 Uhr
Das ist alles sehr wahr: diese Lösung Wille Arbeit. Ich sage nur, dass dies keine ist real Lösung des Problems: Sie können immer noch keinen Wraparound erkennen. Denn wenn Sie eine solche Lösung finden, spielt es keine Rolle, ob Ihre Uhr schneller wird und jede Pikosekunde tickt (in diesem Fall beträgt die Zeit bis zum Zählerumbruch nur ein halbes Jahr!).
– mtvec
23. Juni 2010 um 7:28 Uhr
John R. Strohm
Der einfachste Weg, dies zu tun, besteht darin, einen “Epochenzähler” zu erstellen, der Rollover explizit zählt. (Beispiel: Sie haben einen Hardwarezähler, der Sekunden von 0 bis 59 zählt. Ihr Epochenzähler würde Minuten zählen, indem er jedes Mal erhöht wird, wenn er bemerkt, dass der Sekundenzähler übergelaufen ist.)
Ihre future_scheduler-Funktion liest dann die aktuelle Epoche und Zeit und berechnet eine neue Epoche und Zeit für Ihr Ereignis.
Alternativ könnten Sie einfach punten und Ihre Zeitmessungsfunktion dazu bringen, Ihre Ereignispläne bei jedem Timer-Tick auf Null zu zählen.
Das ist nur Verzögerung der Ausführung. Schließlich wird auch der zweite Zähler überlaufen.
– mtvec
22. Juni 2010 um 17:46 Uhr
@Job: Ja, aber es ist eine höllische Verzögerung. Zwei hoch 64 ermöglicht 18.446.744.073.709.551.616 Ticks. Wenn jeder Tick eine Millisekunde ist, dann ergibt das eine Zeitspanne von etwas mehr als 580 Millionen Jahren.
– Torak
22. Juni 2010 um 17:55 Uhr
Sicher, alles, was ich sagen wollte, ist, dass dies keine wirkliche Lösung für das Problem ist.
– mtvec
22. Juni 2010 um 18:10 Uhr
Eine Lösung, die für Zeiträume von weniger als 580 Millionen Jahren funktioniert, ist keine “echte” Lösung des Problems? Warum nicht?
– Mike Pelley
22. Juni 2010 um 19:33 Uhr
Das ist alles sehr wahr: diese Lösung Wille Arbeit. Ich sage nur, dass dies keine ist real Lösung des Problems: Sie können immer noch keinen Wraparound erkennen. Denn wenn Sie eine solche Lösung finden, spielt es keine Rolle, ob Ihre Uhr schneller wird und jede Pikosekunde tickt (in diesem Fall beträgt die Zeit bis zum Zählerumbruch nur ein halbes Jahr!).
– mtvec
23. Juni 2010 um 7:28 Uhr
pmod
Eine der Möglichkeiten besteht darin, beide Variablen auf 64-Bit-Länge umzuwandeln und dann zu summieren. Vergleichen Sie danach mit dem maximalen 32-Bit-Wert, um festzustellen, ob er umschlossen ist.
Die meisten eingebetteten Ziele unterstützen keine 64-Bit-Ganzzahlen.
– Tomlogik
23. Juni 2010 um 14:44 Uhr
In diesem Fall kann ein einfacher Wrapper verwendet werden, der Operationen mit 64-Bit mit Hilfe von 2 x 32-Bit emuliert (ich nehme an, es gibt viele fertige Implementierungen).
– pmod
23. Juni 2010 um 17:52 Uhr
11450300cookie-checkUmgang mit einem Wrapping-Zähler in Embedded Cyes
Wie hoch ist Ihre Taktrate und bei welchem Wert beginnt der Zähler? Könnten Sie auch mehr Details über die Plattform bearbeiten, auf der Sie laufen (Betriebssystem, Chipsatz, Board-Hersteller usw.). Möglicherweise gibt es einige plattformspezifische Lösungen.
– A. Abgabe
22. Juni 2010 um 17:43 Uhr