Per default ist uwTick eine 32bit variable?!? Mit 1ms tick time wird
diese zwangsläufig nach 49.7 Tagen überlaufen. Im HAL sehe ich keine
Vorkehrungen diesbezüglich (z.b. in der HAL delay funktion).
Folgende Fragen:
1. WTF ST?!?
2. Giebts irgendwo eine Einstellung, dass diese per default als 64bit
variable ausgeführt wird?
Falls dies nicht möglich:
3. Wenn ich HAL_IncTick sowie HAL_GetTick im usercode überschreibe, was
muss ich alles beachten, damits weiterhin kompatibel ist mit dem HAL?
4. Wie kann ich sicherstellen, dass das HAL nicht nach 49.7 Tagen
crasht?
Wieso “crasht” der deiner Meinung nach?
Solange Du keine Zeitspannen größer als 49 Tage messen willst ist das ja
kein Problem. Solange Du den alten Vergleichswert im gleichen UINT32
speicherst kannst Du die ohne weiteres voneinander abziehen. Kannst ja
mal zwei UINT32 definieren und 0x00000010-0xFFFFFFF0 ausrechnen lassen.
Donald schrieb:> WTF
Wieso WTF? Was wäre dir denn lieber, dass der Mikrocontroller vorher
angehalten wird und streikt?
Donald schrieb:> Giebts irgendwo eine Einstellung, dass diese per default als 64bit> variable ausgeführt wird?
WTF? Die 64 Bit laufen auch irgendwann über. Damit verschiebst du das
Problem nur auf später (ja ich weiß, bis dahin sind wir eh alle tot).
Außerdem sind dann alle Zugriffe nicht mehr Atomar, brauchen also
zusätzlich Semaphoren. Bei so kleinen Intervallen ist das keine gute
Idee. Der Mikrocontroller soll schließlich noch etwas anderes machen
können, als nur Millisekunden zu zählen.
Harald A. schrieb:> Wieso “crasht” der deiner Meinung nach?
nun die hal delay funktion dauert dann halt anstelle einiger ms 49 Tage.
Dies darf man wohl als crash bezeichnen:P.
Stefan F. schrieb:> Die 64 Bit laufen auch irgendwann über.
ja genau, aber nicht mehr in unserem Sonnensystem (also wo die sonne
noch brennt :P)
Donald schrieb:> nun die hal delay funktion dauert dann halt anstelle einiger ms 49 Tage.
Nein, das stimmt nicht. Auch während eines Überlaufs kannst du
Intervalle bis 49 Tage korrekt messen bzw. pausieren.
1
uint32_tstart,duration;
2
start=HAL_GetTick();
3
tuetwas...
4
duration=HAL_GetTick();
oder:
1
uint32_tstart;
2
while(HAL_GetTick()-start<10000);// 10s warten
Die "duration" ist richtig, auch wenn der Timer zwischendurchn einmal
überläuft.
Wichtig ist dabei die Subtraktion. Mit einer Addition funktioniert es
nicht korrekt:
Es handelt sich hier um ms.
Wenn es zum Überlauf kommt, einfach einen Rundenzähler bei Bedarf
erhöhen.
Das reicht dann bis zur Ewigkeit und darüber hinaus. :)
Ich würde sagen WTF lern grundlagen.
Such mal bei Goolge oder einer anderen Suchmaschine deiner Wahl nach
"Arduino millis() überlauf", vielleicht ist das mehr auf deinem Niveau
erklärt.
Stefan F. schrieb:> Nein, das stimmt nicht.Stefan F. schrieb:> Wichtig ist dabei die Subtraktion. Mit einer Addition funktioniert es> nicht korrekt:
stimmt, genau mein denkfehler, danke
edit: quatsch: subtraktion hat das gleiche Problem, wenn der Zählerwert
tief ist...
Vielleicht so? Dann scheint es zu funktionieren. Wir nehmen mal an, dass
der Zähler nur 3 Bit breit ist und dass die Subtraktion intern als
Addition mit dem negativen Wert ausgeführt wird.
zum Beispiel 2 minus 1:
2 ist 010;
das Komplement von 1 ist 110, plus 1 ergibt 111;
010 plus 111 ergibt 1001, das wird bei 3 Bit abgeschnitten, ergibt 001
1
angenommen, start ist 011, das Komplement davon 100, plus 1 macht 101.
2
Zähler -start Zähler+(-start) 3 Bit
3
100 101 1001 001 // 4 - 3 = 1
4
101 101 1010 010
5
110 101 1011 011
6
111 101 1100 100 // 7 - 3 = 4
7
000 101 101 101 // 0 - 3 = 5
8
001 101 110 110 // 1 - 3 = 6
Aber auf einem Cortex-M4 ist nicht einmal ein 32-Zähler garantiert
atomar, wenn nämlich die Variable nicht word aligned ist. Oder ist sie
das immer? Ehrlich? Umgekehrt kann auch ein 64-Bit Zähler funktionieren,
wenn man zum Lesen LDRD nimmt und die Timer-Interupt-Routine nicht
unterbrochen werden kann. Oder?
Bauform B. schrieb:> wenn nämlich die Variable nicht word aligned ist. Oder ist sie> das immer?
Wenn man dem Compiler nichts anderes Mitteilt, würde ich mich wundern,
wenn die Variablen nicht aligned sind.
Bauform B. schrieb:> Aber auf einem Cortex-M4 ist nicht einmal ein 32-Zähler garantiert> atomar, wenn nämlich die Variable nicht word aligned ist. Oder ist sie> das immer?
Mit den Standardeinstellungen ist sie das. Und ja, wenn man unbedingt
will, kann man sein eigenes Programm sabotieren.
Bauform B. schrieb:> Umgekehrt kann auch ein 64-Bit Zähler funktionieren,> wenn man zum Lesen LDRD nimmt und die Timer-Interupt-Routine nicht> unterbrochen werden kann. Oder?
Es geht nicht nur um die Timer ISR, sondern um die Konsumenten des
Zählerstandes. Da musst du immer mit Unterbrechungen rechnen, es sei
denn, du blockierst sie absichtlich.
Steve van de Grens schrieb:> Bauform B. schrieb:>> Umgekehrt kann auch ein 64-Bit Zähler funktionieren,>> wenn man zum Lesen LDRD nimmt und die Timer-Interupt-Routine nicht>> unterbrochen werden kann. Oder?>> Es geht nicht nur um die Timer ISR, sondern um die Konsumenten des> Zählerstandes. Da musst du immer mit Unterbrechungen rechnen, es sei> denn, du blockierst sie absichtlich.
Ja, genau. Der LDRD Befehl kann unterbrochen werden, aber er wird danach
neu gestartet. Ob sich der Zählerstand während der Unterbrechung ändert,
ist egal. Erst wenn beide Hälften des 64-Bit-Zähler geladen wurden, kann
der Konsument weiter laufen. Oder wie soll ich das Handbuch¹ verstehen:
1
A3.5.3 Atomicity in the ARM architecture
2
In ARMv7-M, the single-copy atomic processor accesses are:
3
• All byte accesses.
4
• All halfword accesses to halfword-aligned locations.
Bauform B. schrieb:> aber er wird danach neu gestartet
Ah, gut zu wissen. Danke dass du darauf hingewiesen hast. Damit hätte
ich gar nicht gerechnet, mit so einem Feature hatte ich noch nie zu tun.
Donald schrieb:> Per default ist uwTick eine 32bit variable?!? Mit 1ms tick time wird> diese zwangsläufig nach 49.7 Tagen überlaufen. Im HAL sehe ich keine> Vorkehrungen diesbezüglich
Ich werde dich bei passender Gelegenheit deswegen mal gebührend
bedauern.
Aber wozu so eine blöde Überlegung?
Normalerweise sollte man für eine Anwendung auch die Funktionalität (die
man sich SELBER erarbeitet) planen. Und wenn du Verzögerungszeiten von
50 Tagen oder mehr benötigst, dann brauchst du ganz gewiß nicht die
Auflösung in Millisekunden.
Ganz generell: einfach nur stur zu brüllen "ich brauche mehr Bitbreite"
ist das Gegenteil von klugem Programmieren. Jede Variable, die nicht
unendlich viele Bit breit ist, läuft irgendwann mal über. Und der Ansatz
"wenn's nur weit genug von jetzt ist, dann ist's mir egal - nach mir die
Sintflut" mag praktikabel sein, ist aber im Kern unschön.
Ich habe sowas anders gelöst, hab das auch hier mal gepostet, falls du
Bedarf haben solltest, dann suche einfach danach.
W.S.
W.S. schrieb:> der Ansatz> "wenn's nur weit genug von jetzt ist, dann ist's mir egal - nach mir die> Sintflut" mag praktikabel sein, ist aber im Kern unschön.
Ich erinnere nur an den Jahr 2000 Bug. Das nächste Problem steht bereits
für Januar 2038 an, weil dann die 32 Bit Systemzeit (in Sekunden seit
1.1.1970) überläuft.
Wer damals "Nach mir die Sinntflut" dachte, den hasse ich jetzt schon
dafür.