Forum: Mikrocontroller und Digitale Elektronik ARM M4 (stm32): free running timer statt systick interrupt


von ARM M4 (stm32) (Gast)


Lesenswert?

Hi,

warum benutzt man auf ARM System standardmäßig den Systick Interrupt als 
Zeitbasis, anstelle eines free running timers?

Angenommen man hätte noch einen freien Timer über, könnte man diesen per 
Prescaler auf 1kHz einstellen (z.B. 50Mhz ABP1 und Prescaler 50k) und 
bräuchte somit gar keine Interrupts für die Zeitbasis.

Das geht je nach System und Clockfrequenzen nicht immer, scheint mir 
aber eine elegantere Lösung zu sein.

Was sagt ihr dazu?

von pegel (Gast)


Lesenswert?

Alle Timeouts z.B. für die Peripherie nutzen den Systick, da ist es doch 
sinnvoll wenn man schon einen Bezug hat.

Wenn Du selbst erst den Timer irgendwie einstellen musst, oder eben auch 
nicht, wie soll das funktionieren?

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

ARM M4 (stm32) schrieb im Beitrag #6448367:
> Systick Interrupt als Zeitbasis, anstelle eines free running timers
Das ist eigentlich genau das gleiche.

Nur das der Timer mit dem Namen Systick in der ARM-Spezifikation 
einheitlich vorgegeben ist wärend bei den anderen Timern  jeder 
Hersteller machen kann was er will und das sogar je nach Modell 
teilweise noch unterschiedlich.
Eleganter ist es daher eher denn portablen Systick zu nehmen (der eh so 
eingeschränkt ist das man ihn kaum für was anderes nehmen kann) als 
einen der proprietären Timer. Wenn der Systick aber mal nicht passen 
sollte kann man aber durchaus auch einen der anderen Timer nehmen.

von Adam P. (adamap)


Lesenswert?

Da man die "normalen" Timer z.B. für PWM oder für andere Zählvorgänge 
benötigen könnte, wurde der SysTick festgelegt um eine Spezifikation für 
diverse OS zu haben.

Diese nutzen den SysTick z.B. für den Kontextwechsel bei Multitasking.

"The System Tick Time (SysTick) generates interrupt requests on a 
regular basis. This allows an OS to carry out context switching to 
support multiple tasking. For applications that do not require an OS, 
the SysTick can be used for time keeping, time measurement, or as an 
interrupt source for tasks that need to be executed regularly."

https://arm-software.github.io/CMSIS_5/Core/html/group__SysTick__gr.html

von Ben S. (bensch123)


Lesenswert?

ARM M4 (stm32) schrieb im Beitrag #6448367:
> warum benutzt man auf ARM System standardmäßig den Systick Interrupt als
> Zeitbasis, anstelle eines free running timers?

Die Frage ist, in welchem Bezug? Ich habe z.B. eine Software 
Timerklasse, welche als 32bit Zeitbasis einen Zeiger benutzt. Und diesen 
kann ich natürlich auf das zeigen lassen wo ich Lust drauf habe.

Für Echtzeitsysteme solltest du dann den Systemtick nutzen weil wie hier 
schon geschrieben: Genau spezifiziert und Teil des ARM Cores.

Ich benutze aber gerne 32bit und nicht diese seltsamen 24bit. Daher 
reserviere ich mir immer einen normalen 32bit Timer als Referenz für 
meine Softwaretimer - es sei denn es geht nicht anders.

: Bearbeitet durch User
von A. S. (Gast)


Lesenswert?

ARM M4 (stm32) schrieb im Beitrag #6448367:
> und bräuchte somit gar keine Interrupts für die Zeitbasis.

Und wer zählt die ms?

Abgesehen von den Dingen, die sowieso im Interrupt gemacht werden 
müssen, wenn man ein OS hat.

von Stefan F. (Gast)


Lesenswert?

ARM M4 (stm32) schrieb im Beitrag #6448367:
> warum benutzt man auf ARM System standardmäßig den Systick Interrupt als
> Zeitbasis, anstelle eines free running timers?

Der Systick Timer existiert in allen ARM Cortex Controllern, deswegen 
standardmäßig.

Bei einem freilaufenden Zähler müsste man "krumme" Quarz-Frequenzen 
verwenden, um auf Millisekunden zu kommen. Man hat da aber nicht immer 
die freie Wahl, denn USB geht z.B. nur mit 48 oder 72 MHz Systemtakt.

von Bauform B. (bauformb)


Lesenswert?

ARM M4 (stm32) schrieb im Beitrag #6448367:
> Angenommen man hätte noch einen freien Timer über, könnte man diesen per
> Prescaler auf 1kHz einstellen (z.B. 50Mhz ABP1 und Prescaler 50k) und
> bräuchte somit gar keine Interrupts für die Zeitbasis.

Man kann den SYSTICK auch wie einen "normalen" Timer benutzen und 
auslesen. Er hat ein COUNTFLAG, also braucht man keinen Interrupt. Das 
Flag setzt sich sogar beim Lesen automatisch zurück. Was auch ein paar 
Taktzyklen spart, wenn man den Interrupt doch benutzt.

Noch ein Bonus: beim STM32 haben die meisten Timer ja nur 16 Bit, der 
SYSTICK hat immerhin 24. Ich glaube, ich würde eher auf alle anderen 
Interrupts verzichten als auf den systick...

Stefan ⛄ F. schrieb:
> Bei einem freilaufenden Zähler müsste man "krumme" Quarz-Frequenzen
> verwenden, um auf Millisekunden zu kommen. Man hat da aber nicht immer
> die freie Wahl, denn USB geht z.B. nur mit 48 oder 72 MHz Systemtakt.

Naja, so ein Zähler wäre ja noch abgespeckter als der systick, der 
sollte sich aber nicht "Timer" nennen dürfen.

von Ben S. (bensch123)


Lesenswert?

Stefan ⛄ F. schrieb:
> Bei einem freilaufenden Zähler müsste man "krumme" Quarz-Frequenzen
> verwenden, um auf Millisekunden zu kommen. Man hat da aber nicht immer
> die freie Wahl, denn USB geht z.B. nur mit 48 oder 72 MHz Systemtakt.

Klär' mich mal auf? Wenn ich einen 12MHz Quarz nutze, dann nehmen ich 
den * 4 und ich habe meinen USB Takt und teile den durch 12000, dann 
habe ich meine 1ms -> 12MHz ist aber weit davon entfernt eine krumme 
Quarz Frequenz zu sein.

von Stefan F. (Gast)


Lesenswert?

Ben S. schrieb:
> Wenn ich einen 12MHz Quarz nutze, dann nehmen ich
> den mal 4 und ich habe meinen USB Takt und teile den durch 12000

Eben nicht!

Wenn dein Zähler von 0 bis 11999 läuft, dann enthält sein Zählregister 
nur Bruchteile von Millisekunden. Was dir dann fehlt ist die Zählung der 
Millisekunden. Dafür bräuchtest du dann wieder eine ISR und dann bist du 
genau bei dem Konzept des Systick.

Ohne ISR braucht man ein mehrstufiges Konzept wie bei der RTC. Da hast 
du einen Timer mit konfigurierbaren Endwert (der jede Sekunde 
überläuft), und dahinter einen zweiten Zähler der die Sekunden zählt 
(=Unix Zeitstempel).

By the way: Der Systick muss nicht unbedingt Millisekunden zählen. Wenn 
man will, kann man ihn auch für Sekunden oder irgendwelche anderen 
Zeitabschnitte benutzen. Beim Systemtimer des PC waren lange Zeit 20ms 
Ticks üblich.

von Ben S. (bensch123)


Lesenswert?

Stefan ⛄ F. schrieb:
> Wenn dein Zähler von 0 bis 11999 läuft, dann enthält sein Zählregister
> nur Bruchteile von Millisekunden. Was dir dann fehlt ist die Zählung der
> Millisekunden.

Dafür kannst du den Prescaler einstellen (bei STM32). Dann zählt der 
Timer genau jede Millisekunde eins hoch - mache ich immer so und 
funktioniert bestens.
1
TIM2->PSC = (12000000UL / 1000) - 1;

Für meine Softwaretimer lasse ich sogar jede Mikrosekunde hochzählen und 
nutze den Interrupt um einen 64bit Zeitstempel zu erzeugen. Dann kann 
ich Softwaretimer mit Mikrosekunden Bereich erzeugen, welche erst nach 
ca. 600.000 Jahren einen Überkauf im 64bit Zeitstempel erzeugen.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> Stefan ⛄ F. schrieb:
>> Wenn dein Zähler von 0 bis 11999 läuft, dann enthält sein Zählregister
>> nur Bruchteile von Millisekunden. Was dir dann fehlt ist die Zählung der
>> Millisekunden.

Ben S. schrieb:
> Dafür kannst du den Prescaler einstellen (bei STM32). Dann zählt der
> Timer genau jede Millisekunde eins hoch - mache ich immer so und
> funktioniert bestens.
> TIM2->PSC = (12000000UL / 1000) - 1;

Ja kannst du machen. Der Systick Timer hat aber leider keinen Prescaler.

von Ben S. (bensch123)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ja kannst du machen. Nur hat der Systick Timer keinen Prescaler.

Das ist dann wohl ein Nachteil des Systick Timers, für eigene Entwürfe 
spielt der bei mir keine Rolle.

von Stefan F. (Gast)


Lesenswert?

Ben S. schrieb:
> Das ist dann wohl ein Nachteil des Systick Timers, für eigene Entwürfe
> spielt der bei mir keine Rolle.

Ist OK. Nutze die Hardware so, wie es dir am besten passt.

von Johannes S. (Gast)


Lesenswert?

Z.B. im Mbed-os wird der Systick nicht verwendet sondern ein Timer mit 1 
µs Basistakt. Die Timer Klasse braucht dann keine eigenen HW Timer 
sondern nutzt diesen 1 µs Basistakt für Zeitmessungen. Ebenso eine 
Ticker Klasse die zyklische Aktionen behandeln kann. Die laufen dann 
aber im Interruptkontext und damit sollte man sparsam sein.
Das OS arbeitet damit für Targets die einen low power timer haben 
tickless, d.h. ein sleep_for(100ms) legt die CPU tatsächlich für 100 ms 
schlafen um Strom zu sparen.
USB beeinflusst nur den max. Takt wenn sich bei dem keine 48 MHz 
einstellen lassen. Die modernen MCU haben da aber mittlerweile viele 
Möglichkeiten.

von Ben S. (bensch123)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ist OK. Nutze die Hardware so, wie es dir am besten passt.

Aber wo ist das genaue Problem? Wenn ich z.B. einen 8MHz Quarz nutze, 
dann geht der laut Datenblatt meines µC (STM32) /8 zum Systick, also 
1MHz. Damit lässt sich prima ein 1ms Überlauf erzeugen.

Oder möchtest du, dass der Systick wirklich jede mS +1 macht? Wenn der 
keinen Prescaler hat (ich nutze den so selten ... ok eigentlich nie), 
dann müsste der SYSCLK ja 8000Hz betragen - das ergibt für mich keinen 
Sinn? Und mit einem 8MHz Quarz kann ich prima die 48 MHz für USB 
erzeugen.

Wo ist mein Fehler 👍?

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Ben S. schrieb:
> Aber wo ist das genaue Problem? Wenn ich z.B. einen 8MHz Quarz nutze,
> dann geht der laut Datenblatt meines µC (STM32) /8 zum Systick, also
> 1MHz.

Bist du da sicher? Bei all meinen STM32 wird der SysTick vom 
Platform-Takt abgeleitet, also z.B. 72 MHz und das kann man in SYST_CSR 
einstellen.

W.S.

von Stefan F. (Gast)


Lesenswert?

Ben S. schrieb:
> Aber wo ist das genaue Problem? Wenn ich z.B. einen 8MHz Quarz nutze,
> dann geht der laut Datenblatt meines µC (STM32) /8 zum Systick, also
> 1MHz. Damit lässt sich prima ein 1ms Überlauf erzeugen.

Ja, diese Überläufe kannst du in der ISR zählen. Das ist das Konzept des 
Systick timers.

Wenn du aber die Überläufe in Hardware zählen willst, anstatt ISR, 
brauchst du einen zweistufigen Timer. Also ein Zähler der die 
gewünschten Intervalle/Überläufe erzeugt, und dahinter ein zweiter 
Zähler, der die Überläufe zählt. Die gibt es auch, also kein Problem.

Der Punkt auf den ich hinweisen wollte ist: Mit dem Systick alleine geht 
es nicht. Weil der eben nur einstufig ist.

von Ben S. (bensch123)


Lesenswert?

W.S. schrieb:
> Bist du da sicher? Bei all meinen STM32 wird der SysTick vom
> Platform-Takt abgeleitet, also z.B. 72 MHz und das kann man in SYST_CSR
> einstellen.

Bin ich nicht, deswegen frage ich ja! Bei meinen mir spontan 
vorliegenden Datenblättern geht der SYSCLK / 8 -> System timer (das ist 
doch der ticker oder?).

von Stefan F. (Gast)


Lesenswert?

Ben S. schrieb:
> Bin ich nicht, deswegen frage ich ja! Bei meinen mir spontan
> vorliegenden Datenblättern geht der SYSCLK / 8 -> System timer (das ist
> doch der ticker oder?).

Ist egal ob durch 8 geteilt oder nicht. Für die Frage, welche Art von 
Timer/Zähler man braucht, spielt das keine Rolle.

Dann teilt man halt ggf. durch 8000 statt 1000.

von Ben S. (bensch123)


Lesenswert?

Stefan ⛄ F. schrieb:
> Wenn du aber die Überläufe in Hardware zählen willst, anstatt ISR,
> brauchst du einen zweistufigen Timer. Also ein Zähler der die
> gewünschten Intervalle/Überläufe erzeugt, und dahinter ein zweiter
> Zähler, der die Überläufe zählt. Die gibt es auch, also kein Problem.

Habe ich noch nie benutzt, ist mir aber bewusst. Wofür nutzt man sowas 
idR?

von Stefan F. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
>> Wenn du aber die Überläufe in Hardware zählen willst, anstatt ISR,
>> brauchst du einen zweistufigen Timer. Also ein Zähler der die
>> gewünschten Intervalle/Überläufe erzeugt, und dahinter ein zweiter
>> Zähler, der die Überläufe zählt. Die gibt es auch, also kein Problem.

Ben S. schrieb:
> Habe ich noch nie benutzt, ist mir aber bewusst. Wofür nutzt man sowas
> idR?

Doch hast du. Siehe deine eigenen Worte "mache ich immer so":

Ben S. schrieb:
> Dafür kannst du den Prescaler einstellen (bei STM32). Dann zählt der
> Timer genau jede Millisekunde eins hoch - mache ich immer so und
> funktioniert bestens.
> TIM2->PSC = (12000000UL / 1000) - 1;

Der Prescaler ist die erste Stufe die glatte ms erzeugt, der Counter ist 
die zweite Stufe, die ms zählt.

von Ben S. (bensch123)


Lesenswert?

Stefan ⛄ F. schrieb:
> Der Prescaler ist die erste Stufe die glatte ms erzeugt, der Counter ist
> die zweite Stufe, die ms zählt.

Naja, ich meinte etwas anderes. Du kannst ja z.B. bei STM32 die Timer 
verknüpfen. Überlauf Timer A - > Zählen Timer B. Ich dachte du meinst 
sowas.

Auch wenn ich den Prescaler nutze habe ich trotzdem nur Zugriff auf 
einen Zählerstand, nämlich TIM2->CNT.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Zweistufiger Timer:
1
              Stufe 1                Stufe 2
2
             ___________            ___________
3
            | Prescaler |          |           |
4
8 MHz ------|   ÷8000   |---1kHz---|  Counter  |
5
            |___________|          |___________|

Wer mit dem Systick Millisekunden zählen will, muss die zweite Stufe in 
Software (in der ISR) implementieren, weil die Hardware des Systick nur 
eine Stufe hat.

1
              Stufe 1                Stufe 2
2
             ___________            ___________
3
            |  Systick  |          |           |
4
8 MHz ------|   ÷8000   |---1kHz---|   ISR     |
5
            |___________|          |___________|

von ARM M4 (stm32) (Gast)


Lesenswert?

Leute,

hier mal mein Beispiel, was bei mir auf dem Tisch liegt:
STM32F733 (mit USB HS PHY :) ), 12Mhz Quarz, Sysclock auf 200Mhz 
eingestellt, USB48Mhz geht auch, APB1 Timer Clock auf 50Mhz eingestellt, 
kein RTOS geplant.

Also Timer2 (50MHz) -> Prescaler 50k -> macht jede ms ein Inkrement.
Siehe auch Beitrag über mir.

Im STM32 Universum überschreibe ich dann die Funktion
1
uint32_t GetTick() {
2
    return __HAL_TIM_GET_COUNTER(&htim2); 
3
}

und fertig.

Nochmal die Vorteile:
-> kein Interrupt
   -> Zeitbasis ist immer verfügbar, auch in kritischen 
Sektionen/anderen Interrupts
   -> minimal bessere Performance
   -> kein möglicher Jitter durch Systick Interrupt bei kritischen 
Timings
   -> man kann sogar einen zweiten Timer kaskadieren und somit eine nie 
überlaufende Zeitbasis erstellen die komplett ohne den CPU Core läuft

Nachteile:
-> RTOS brauchen einen (Systick) Interrupt für Context Switching etc.

Ja klar muss man einen Timer über haben und der Takt muss passen, 
mindestens ersteres dürfte aber häufig vorkommen. ARM hat halt leider 
keinen Prescaler für den Systick vorgesehen, ansonsten hätten sich 
bestimmt die 2 Optionen mit Interrupt / "direkt" ohne Interrupt 
etabliert.

Die Kommonalität und nötige Hardwareabstraktion ist voll gegeben, denn 
das wird über die obige Funktion hergestellt. Gibt schließlich auch M0 
ohne Systick.


Ich habe es schon probiert und festgestellt, dass es mit STM32Cube 
generiertem Code nicht direkt funktioniert, und zwar weil die Timer erst 
nach USB und HAL initialisiert werden, die aber bereits GetTick() 
benutzen (-> Deadlock).
Lässt sich aber sicherlich fixen.

von Johannes S. (Gast)


Lesenswert?

ARM M4 (stm32) schrieb im Beitrag #6449393:
> Lässt sich aber sicherlich fixen.

Klar. Wenn man HAL_GetTick() überschreibt und andere Timer benutzt, dann 
sollte man die vielleicht auch in
HAL_InitTick() erstmal initialisieren.

ARM M4 (stm32) schrieb im Beitrag #6449393:
> Nachteile:
> -> RTOS brauchen einen (Systick) Interrupt für Context Switching etc.

Nein, nicht zwingend. Siehe Tickless.

von Stefan F. (Gast)


Lesenswert?

ARM M4 (stm32) schrieb im Beitrag #6449393:
> Nochmal die Vorteile

Ich glaube, das war schon vorher klar. Deine alternative Methode hat ja 
auch niemand in Frage gestellt.

> Ich habe es schon probiert und festgestellt, dass es mit
> STM32Cube generiertem Code nicht direkt funktioniert, und
> zwar weil die Timer erst nach USB und HAL initialisiert werden,
> die aber bereits GetTick() benutzen (-> Deadlock).

Siehe erste Antwort von pegel. Kaum macht man es richtig, funktioniert 
es auch :-)

von Nop (Gast)


Lesenswert?

Ben S. schrieb:

> Bin ich nicht, deswegen frage ich ja! Bei meinen mir spontan
> vorliegenden Datenblättern geht der SYSCLK / 8 -> System timer

Aber SYSCLK ist nicht der Takt direkt vom Quarz, sondern das, womit die 
CPU läuft, da hat W.S. schon recht. Also der Takt, der nach der PLL 
rauskommt, nicht deren Eingang.

Außerdem ist /8 auch nur dann, wenn man das im Systick-Control-Register 
so einstellt.

von Johannes S. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Siehe erste Antwort von pegel.

ich kenne keine Peripherie die den Sysclock braucht oder von sich aus 
Timeouts kennt. Das impliziert wohl die Benutzung von HAL, aber davon 
steht nix in der Frage.

von Stefan F. (Gast)


Lesenswert?

Johannes S. schrieb:
> ich kenne keine Peripherie die den Sysclock braucht oder von sich aus
> Timeouts kennt. Das impliziert wohl die Benutzung von HAL

Klaro, es ist die Software gemeint, die auf Peripherie zugreift. Als 
Beispiel wurde USB genannt.

von pegel (Gast)


Lesenswert?

Ja, ich gestehe, ich bin ein Freund von HAL.

Heutzutage wo wir genug Speicher haben, kann man sich ruhig etwas Luxus 
leisten und es muss nicht alles Minimalistisch aufs Byte genau berechnet 
werden.

von Johannes S. (Gast)


Lesenswert?

ja, nur USB hat damit nix zu tun. Solange eine Quarz Frequenz von n * 1 
MHz verwendet wird, kann man immer einen Timer mit 1 µs Auflösung laufen 
lassen und daraus auch einen 1 ms Interrupt generieren (wenn nötig). Und 
darum ging es ja. Und auch wenn man eine Systemzeit in ms habe möchte, 
dann braucht man keinen zyklischen 1 ms Interrupt.

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
Noch kein Account? Hier anmelden.