Forum: Mikrocontroller und Digitale Elektronik STM32 - HAL Delay gut?


von Verzögerer (Gast)


Lesenswert?

Guten Abend ans Forum,

ich versuche mich gerade etwas an STM32 Controllern. Irgendwann kommt 
man ja an den Punkt, wo mehrere Sachen quasi-parallel laufen sollen.

Bisher verwende ich "HAL_Delay(1000)" um eine Sekunde zu warten. Mir war 
aus der AVR Welt noch bekannt, dass die Delay Sache den Controller 
komplett lahm legt (User Eingaben werden nicht erkannt etc).

Auf der Suche nach dem besseren Weg, bin ich auf die Implementierung von 
HAL_DELAY gestoßen.

Frage 1: Blockiert HAL_DELAY mein Hauptprogramm wie bei den AVRs? Nach 
meinem Verständnis hängt ja er ja blöd in der while Schleife rum und 
User Eingaben im Hauptprogramm gehen verloren. Liege ich richtig?
1
__weak void HAL_Delay(uint32_t Delay)
2
{
3
  uint32_t tickstart = HAL_GetTick();
4
  uint32_t wait = Delay;
5
  /* Add a freq to guarantee minimum wait */
6
  if (wait < HAL_MAX_DELAY)
7
  {
8
    wait += (uint32_t)(uwTickFreq);
9
  }
10
  while ((HAL_GetTick() - tickstart) < wait)
11
  {
12
  }
13
}

Wäre dann diese Art der Implementierung besser?

https://embeddedexpert.io/?p=246

Oder eine ganz andere?

Beste Grüße
Max

von Harry L. (mysth)


Lesenswert?

Verzögerer schrieb:
> Frage 1: Blockiert HAL_DELAY mein Hauptprogramm wie bei den AVRs?

JA

Wenn du ein nicht blockierendes Delay benötigst, schau dir FreeRTOS und 
da osDelay() an! (ist in der HAL enthalten)

: Bearbeitet durch User
von olaf (Gast)


Lesenswert?

> Wäre dann diese Art der Implementierung besser?

Was erwartest du das dein Controller bei einem delay macht?
IRQs werden weiterlaufen, aber sonst steht natuerlich alles
wenn du kein Multitasking-OS verwendet.

Du kannst das hoechstens selbst entschaerfen in dem du dir
ein, ein Ticker_Start() und eine Ticker_Ask(1000) programmierst.

Dann sowas:

Ticker_Start();
do
{
//  Hier kannst du noch was machen
}while(Ticker_Ask(1000);

Olaf

von Wühlhase (Gast)


Lesenswert?

Ein ungeschicktes Trollthema.

von olaf (Gast)


Lesenswert?

> Ein ungeschicktes Trollthema.

Denkbar, aber du darfst nicht vergessen das der Nachwuchs immer duemmer 
wird, was natuerlich daran liegt das wir vergessen haben wie dumm wir 
waren als wir angefangen haben. :-D

Olaf

von Martin (Gast)


Lesenswert?

Hier ein Pseudocode wie du das machen kannst :

t = timeticks + 1000(ms)
while (1) {
  if (timeticks => t) {
    t = timeticks + 1000(ms)
    mache was auch immer alle 1000 ms
  }
  mache was anderes
}

von stephan (Gast)


Lesenswert?

schau dir mal diese macros an:
1
/*
2
 *  These inlines deal with timer wrapping correctly. You are 
3
 *  strongly encouraged to use them
4
 *  1. Because people otherwise forget
5
 *  2. Because if the timer wrap changes in future you won't have to
6
 *     alter your driver code.
7
 *
8
 * time_after(a,b) returns true if the time a is after time b.
9
 *
10
 * Do this with "<0" and ">=0" to only test the sign of the result. A
11
 * good compiler would generate better code (and a really good compiler
12
 * wouldn't care). Gcc is currently neither.
13
 */
14
#define time_after(a,b)    \
15
  (typecheck(unsigned long, a) && \
16
   typecheck(unsigned long, b) && \
17
   ((long)((b) - (a)) < 0))
18
#define time_before(a,b)  time_after(b,a)

im linux code gibs da noch mehr.

oder du baust dir gleich einen SW-Timer auf!
siehe als Idee z.B.: 
'https://github.com/lmooml/SmartTimer/tree/master/smarttimer';

von Jens R. (tmaniac)


Lesenswert?

Verzögerer schrieb:
> while ((HAL_GetTick() - tickstart) < wait)
>   {
>   }

Warum warten, wenn man auch prüfen kann?
Wirklich, bei 1000ms macht die main( while() ... ) doch viele 
Durchläufe. Also kann man doch mit HAL_GetTick() prüfen ob die Sekunde 
rum ist und dann darauf reagieren.
Sollte diese eben nicht rum sein, kann man allen möglichen anderen Kram 
machen.
Ok es kann passieren das man ein paar Millisekunden zu spät erkennt, 
dass die 1000ms rum sind, aber das muss man selber abschätzen wie 
wichtig das ist.
Wenn die 1000ms wichtig sind sollte man eh auf Timer-Interrupt setzen.

von Michael D. (nospam2000)


Lesenswert?

olaf schrieb:
>> Ein ungeschicktes Trollthema.
>
> Denkbar, aber du darfst nicht vergessen das der Nachwuchs immer duemmer
> wird, was natuerlich daran liegt das wir vergessen haben wie dumm wir
> waren als wir angefangen haben. :-D

 :-)

Es gibt Uncle Bob's Law: Die Anzahl der Entwickler verdoppelt sich alle 
5 Jahre,
siehe hier: 
https://www.linkedin.com/pulse/developer-ranks-double-every-5-years-andy-smith

Dadurch ergibt sich folgende Tabelle, quasi eine Erfahrungspyramide:
50 % der Entwickler haben weniger als 5 Jahre Erfahrung
75 % der Entwickler haben weniger als 10 Jahre Erfahrung
87,5 % der Entwickler haben weniger als 15 Jahre Erfahrung
93,75 % der Entwickler haben weniger als 20 Jahre Erfahrung
...

Je steiler das Wachstum desto größer das Problem.

 Michael

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


Angehängte Dateien:

Lesenswert?

Verzögerer schrieb:
> ich versuche mich gerade etwas an STM32 Controllern. Irgendwann kommt
> man ja an den Punkt, wo mehrere Sachen quasi-parallel laufen sollen.
>
> Bisher verwende ich "HAL_Delay(1000)" um eine Sekunde zu warten.

Anbei ein kleines Stück Quellcode mit dem man das Warten etwas besser 
organisieren kann, ohne dazu gleich irgendwelche Betriebssysteme 
aufzufahren, wie es dir bereits angeraten wurde. Ich hab das vor 
geraumer Zeit schon mal gepostet, aber das Suchen im Forum scheint eher 
unbeliebt zu sein.

Also, zum Prinzip: anstatt mit Warten die Zeit totzuschlagen kann man es 
auch andersherum machen: man stellt sich einen Wecker, der nach xxx 
Sekunden (oder Stunden oder Millisekunden) klingelt. Da kann man in der 
Zwischenzeit was anderes machen oder auf das Klingeln warten - je nach 
Gusto. Der Wecker ist hier der Interrupthandler des Timerticks und das 
Klingeln ist die Event-Verwaltung, genauer ein Event, der zur rechten 
Zeit in die Event-Warteschlange geworfen wird.

Das Beispiel in der ZIP-Datei ist ein Beispiel. Da kommen auch 
Event-Codes und Namen von Programmteilen und anderes Zeugs vor, was du 
vermutlich nicht brauchst. Du kannst es dir also nach deinem Bedarf 
zusammenkürzen und abändern nachdem du das eigentlich recht einfache 
Prinzip verstanden hast.

W.S.

von J. S. (jojos)


Lesenswert?

und was soll so schlimm sein an der Nutzung eines OS? Für allgemeine 
Probleme kann man auch allgemeine Lösungen nehmen. Und Events und Timer 
sind so allgemein das jedes OS sowas an Grundausstattung hat. Mit Doku, 
entwickelt und getestet von großen Communities, ordentlich auf Git 
Servern abgelegt und nicht als undokumentierte Zip Brocken von einem 
Frickler über den Zaun geworfen.
Und das ist auch der Grund warum so etwas nicht gefunden wird, ein Forum 
als Dateiablage ist einfach nur Scheiße.

: Bearbeitet durch User
von olaf (Gast)


Lesenswert?

> und was soll so schlimm sein an der Nutzung eines OS?

Fuer sehr kleine Sachen ist ein OS oftmals uebertrieben weil es eine 
Sache ueberkompliziert oder manchmal auch etwas unmoeglich macht. Erst 
recht fuer einen Anfaenger. Auch das Debuggen komplexer Fehler kann da 
manchmal eine komplexe Freude sein die dich lange beschaeftigt.

Fuer sehr grosse komplexe Sachen ist es manchmal zwingend notwendig.
Zum Beispiel wenn du den Code von einem Dutzend Programmierer
in deinem System hast den du auch etwas getrennt halten willst.

Interessant ist der Zwischenbereich wo man sich nicht sicher ist was 
angemessen ist, da kann man dann trefflich streiten. :-)

Das Eventprinzip das Wolfgang oben nahelegt war auch die Grundlage der 
Palmpiloten.

Vorteil: Man konnte mit wenig Rechenleistung viel erreichen und hatte 
dabei noch eine lange Batterielebensdauer dessen Nutzung eine stete 
Freude war.

Nachteil: Eine Schwachkopfanwendung und dein ganzes System steht.

Olaf

von J. S. (jojos)


Lesenswert?

olaf schrieb:
> Fuer sehr kleine Sachen ist ein OS oftmals uebertrieben weil es eine
> Sache ueberkompliziert oder manchmal auch etwas unmoeglich macht.

Man kann 'kleine' Sachen auch als Übung für größere sehen. Ohne 
Erfahrung gleich ein System mit zig Threads aufzusetzen kann natürlich 
auch reichlich schief gehen.

OS heißt ja nicht unbedingt für alles ein RTOS mit präemptiven Scheduler 
einzusetzen, das Event Prinzip habe ich hier auch schon X-mal gezeigt. 
Das RTOS mit PS hat einen Overhead alleine durch den Stackbereich je 
Thread, aber selbst auf 'kleinen' Cortex-M passt das schon.

Für lange Batterielebensdauer hilft auch ein tickless OS, und da wird es 
schon eine Spur komplexer sowas selber zu bauen.

: Bearbeitet durch User
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.