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.
:
Bearbeitet durch User
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_t start, duration; |
2 | start = HAL_GetTick(); |
3 | tu etwas... |
4 | duration = HAL_GetTick(); |
oder:
1 | uint32_t start; |
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:
1 | uint32_t until; |
2 | until = HAL_GetTick() + 10000; |
3 | while (HAL_GetTick() < until); // 10s warten |
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. :)
Korrektur:
1 | uint32_t start, duration; |
2 | start = HAL_GetTick(); |
3 | tu etwas... |
4 | duration = HAL_GetTick() - start; |
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...
:
Bearbeitet durch User
Donald schrieb: > edit: quatsch: subtraktion hat das gleiche Problem, wenn der Zählerwert > tief ist... Mach doch mal ein Beispiel mit Zahlen bitte.
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?
:
Bearbeitet durch User
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. |
5 | • All word accesses to word-aligned locations. |
6 | LDM, LDC, LDC2, LDRD, STM, STC, STC2, STRD, PUSH, POP, VLDR, |
7 | VSTR, VLDM, VSTM, VPUSH, and VPOP instructions are executed |
8 | as a sequence of word-aligned word accesses. Each 32-bit |
9 | word access is guaranteed to be single-copy atomic. |
10 | A subsequence of two or more word accesses from the sequence |
11 | might not exhibit single-copy atomicity. When an access is |
12 | not single-copy atomic, it is executed as a sequence of |
13 | smaller accesses, each of which is single-copy atomic, at |
14 | least at the byte level. If an instruction is executed as |
15 | a sequence of accesses according to these rules, some |
16 | exceptions can be taken in the sequence and cause execution |
17 | of the instruction to be abandoned. On exception return, |
18 | the instruction that generated the sequence of accesses |
19 | is re-executed and so any accesses that had already been |
20 | performed before the exception was taken might be repeated. |
[1] ARM v7-M Architecture ® Reference Manual, ARM DDI 0403E.d
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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.